Skip to content

Instantly share code, notes, and snippets.

@raymondben
Created April 3, 2019 04:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raymondben/41428babea1e6f1ae0fb1db041f37dfd to your computer and use it in GitHub Desktop.
Save raymondben/41428babea1e6f1ae0fb1db041f37dfd to your computer and use it in GitHub Desktop.
Degrees-minutes-seconds to decimal degrees
#' Convert degrees-minutes-seconds to decimal degrees
#'
#' This is pretty rough and not suitable as-is for public use. But for my own purposes it is more useful than e.g. sp::char2dms
#'
#' @param x character: dms representation
#'
#' @return numeric
#'
#' @export
dms2decdeg <- function(x) {
assert_that(is.character(x))
degree_chars <- paste0("od",intToUtf8(c(176,186,9702))) ## 9702 is white bullet
min_chars <- paste0("m'\u2019",intToUtf8(c(96,180)))
sec_chars <- paste0("\"'\u2019",intToUtf8(c(96,180)))
sgn <- function(x) {
out <- rep(1,length(x))
idx <- grepl("[nesw]",stringr::str_trim(x),ignore.case=TRUE)
out[idx] <-sign(grepl("[ne]",stringr::str_trim(x[idx]),ignore.case=TRUE)-0.5) ## s,w get negative signs
out
}
x <- gsub("\\circ",degree_chars[1],x,fixed=TRUE)
out <- rep(NA,length(x))
## try degrees minutes seconds
this_re <- stringr::regex(paste0("[:space:]*([:digit:]+)[[:space:]",degree_chars,"]+([:digit:]+)[:space:]*[[:space:]",min_chars,"]+([[:digit:]\\.]+)[:space:]*[",sec_chars,"]+[:space:]*([NSEW]?)[:space:]*"),ignore_case=TRUE)
idx <- stringr::str_detect(x,this_re) & is.na(out)
if (any(idx)) {
temp <- stringr::str_match(x,this_re)
out[idx] <- sgn(temp[idx,5])*(as.numeric(temp[idx,2])+as.numeric(temp[idx,3])/60+as.numeric(temp[idx,4])/3600)
}
## try degrees decimal minutes
this_re <- stringr::regex(paste0("[:space:]*([:digit:]+)[[:space:]",degree_chars,"]+([[:digit:]\\.]+)[:space:]*[",min_chars,"]?[:space:]*([NSEW]?)[:space:]*$"),ignore_case=TRUE)
idx <- stringr::str_detect(x,this_re) & is.na(out)
if (any(idx)) {
temp <- stringr::str_match(x,this_re)
out[idx] <- sgn(temp[idx,4])*(as.numeric(temp[idx,2])+as.numeric(temp[idx,3])/60)
}
## try integer degrees
this_re <- stringr::regex(paste0("[:space:]*([:digit:]+)[:space:]*[",degree_chars,"]?[:space:]*([NSEW]?)[:space:]*$"),ignore_case=TRUE)
idx <- stringr::str_detect(x,this_re) & is.na(out)
if (any(idx)) {
temp <- stringr::str_match(x,this_re)
out[idx] <- sgn(temp[idx,3])*(as.numeric(temp[idx,2]))
}
out
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment