#' Transform WGS-84 (Global) coordinates to GCJ-02 (Google CN/Amap)
#'
#' WGS-84 coordinates are gloabal coordinates.
#' This function encrypts it into GCJ-02 that is mandated by Chinese Gov't.
#'
#' @note Latitude is the horizontal line serving as y-axis metric, longitude is
#' the vertical line serving as x-axis metric.
#' @author Yiying Wang, \email{wangy@@aetna.com}
#' @param y \itemize{
#' \item A vector \code{c(latitude, longitude)} \cr
#' \item simply latitude number \cr
#' \item a matrix (row 1-2 or col 1-2). The function will choose how to read the data \cr
#' \item a data.frame (col 1-2)
#' }
#' @param ... \itemize{
#' \item When \code{y} is only latitude, you can pass in \code{x} (longitude) here. \cr
#' \item when \code{y} is a vector of \code{c(lat, lon)}, you can pass in the rest vectors as well.
#' \item when \code{y} is a matrix or a data.frame, ... is omitted.
#' }
#'
#' @seealso \code{\link{convGCJ2WGS}}, \code{\link{convCoord}}.
#' @references
#' \url{https://on4wp7.codeplex.com/SourceControl/changeset/view/21483#353936}
#' @return A 2-col data.frame ([lng, lat]) of transformed coordinates.
#' @export
#' @aliases wgs_to_gcj
#'
#' @examples
#' \dontrun{
#' # Tiananmen square's WGS-84 coordinate is c(39.90734, 116.39089)
#' # http://www.google.cn/maps/place/Tiananmen,+Dongcheng,+Beijing/@39.90874,116.39713,16z?hl=en
#'
#' ## Single point
#' convWGS2GCJ(c(39.90734, 116.39089)) # or
#' convWGS2GCJ(39.90734, 116.39089) # get
#' # lat lng
#' # [1,] 39.90874 116.3971
#'
#' ## Multiple points
#' ### Vectors
#' convWGS2GCJ(c(39.90734, 116.39089), c(39.90734, 116.39089)) # get
#' # lat lng
#' # [1,] 39.90874 116.3971
#' # [2,] 39.90874 116.3971
#'
#' ### Matrix
#' m <- matrix(c(39.90734, 116.39089, 39.90734, 116.39089, 39.90734, 116.39089), nrow=2)
#' m
#' # [,1] [,2] [,3]
#' # [1,] 39.90734 39.90734 39.90734
#' # [2,] 116.39089 116.39089 116.39089
#' convWGS2GCJ(m) # get
#' # lat lng
#' # [1,] 39.90874 116.3971
#' # [2,] 39.90874 116.3971
#' # [3,] 39.90874 116.3971
#'
#' ### data.frame
#' df <- data.frame(lat=c(39.90734, 39.90734, 39.90734, NA),
#' lon=c(116.39089, 116.39089, 116.39089, 116.39089))
#' convWGS2GCJ(df) # get
#' # lat lng
#' # [1,] 39.90874 116.3971
#' # [2,] 39.90874 116.3971
#' # [3,] 39.90874 116.3971
#' # [4,] NA NA
#' }
#'
convWGS2GCJ <- function(y, ...){
# Coord Global GeoSystem (WGS-84) -> Mars GeoSystem (GCJ-02)
# coords must be a vector c(lat,lon)
input <- getCoordArgs(y, ...)
if (! all(abs(input['lat']) <= 90 & abs(input['lon'] <= 180), na.rm=TRUE)){
stop(paste0("Latitude should be within [-90, 90] and longitude ",
"should be within [-180, 180]."))
}
output <- as.data.frame(t(apply(input, MARGIN=1, .wgs2gcj)))
names(output) <- c("lat", "lng")
return(output)
}
#' @export
wgs_to_gcj <- convWGS2GCJ
.wgs2gcj <- function(coord, ...){
A <- aseshms_env$A
EE <- aseshms_env$EE
if (length(coord) > 1){
wgLat <- coord[1]
wgLon <- coord[2]
}else{
wgLat <- coord
wgLon <- unlist(list(...))[1]
}
if (is.na(wgLat) || is.na(wgLon)){
return(c(NA, NA))
}else{
outOfChina <- isOutOfChina(wgLat, wgLon)
if (!outOfChina){
dLat <- transformLat(wgLon - 105.0, wgLat - 35.0)
dLon <- transformLon(wgLon - 105.0, wgLat - 35.0)
radLat <- wgLat / 180.0 * pi
magic <- sin(radLat)
magic <- 1.0 - EE * magic ** 2
sqrtMagic <- sqrt(magic)
dLat <- (dLat * 180.0) / ((A * (1.0 - EE)) / (magic * sqrtMagic) * pi)
dLon <- (dLon * 180.0) / (A / sqrtMagic * cos(radLat) * pi)
WGS2GCJ <- c(lat = wgLat + dLat, lon = wgLon + dLon)
}else{
WGS2GCJ <- c(lat = wgLat, lon = wgLon)
}
}
return(WGS2GCJ)
}
#' Transform GCJ-02 (Google CN/Amap) coordinates to WGS-84 (Global)
#'
#' GCJ-02 is coordinate system mandated by Chinese Gov't.
#' This function decrypts it back to WGS-84 coordinates (gloabal coordinates).
#'
#' @note Latitude is the horizontal line serving as y-axis metric, longitude is
#' the vertical line serving as x-axis metric.
#' @author Yiying Wang, \email{wangy@@aetna.com}
#' @param y \itemize{
#' \item A vector \code{c(latitude, longitude)} \cr
#' \item simply latitude \cr
#' \item a matrix (row 1-2 or col 1-2). The function will choose how to read the data \cr
#' \item a data.frame (col 1-2)
#' }
#' @param ... \itemize{
#' \item When \code{y} is only latitude, you can pass in \code{x} (longitude) here. \cr
#' \item when \code{y} is a vector of \code{c(lat, lon)}, you can pass in the rest vectors as well.
#' \item when \code{y} is a matrix or a data.frame, ... is omitted.
#' }
#'
#' @seealso \code{\link{convWGS2GCJ}}, \code{\link{convCoord}}.
#' @references
#' \url{https://on4wp7.codeplex.com/SourceControl/changeset/view/21483#353936}
#' @return A 2-col data.frame ([lng, lat]) of transformed coordinates.
#' @export
#' @aliases gcj_to_wgs
#'
#' @examples
#' \dontrun{
#' # Tiananmen square's GCJ-02 coordinate is c(39.908746, 116.397131)
#' # http://www.openstreetmap.org/#map=19/39.90734/116.39089
#'
#' ## Single point
#' convGCJ2WGS(c(39.908746, 116.397131)) # or
#' convGCJ2WGS(39.908746, 116.397131) # get
#' # lat lng
#' # [1,] 39.90734 116.3909
#'
#' ## Multiple points
#' ### Vectors
#' convGCJ2WGS(c(39.908746, 116.397131), c(39.908746, 116.397131)) # get
#' # lat lng
#' # [1,] 39.90734 116.3909
#' # [2,] 39.90734 116.3909
#'
#' ### Matrix
#' m <- matrix(c(39.908746, 116.397131, 39.908746, 116.397131, 39.908746, 116.397131),
#' nrow=2)
#' m
#' # [,1] [,2] [,3]
#' # [1,] 39.90875 39.90875 39.90875
#' # [2,] 116.39713 116.39713 116.39713
#' convGCJ2WGS(m) # get
#' # lat lng
#' # [1,] 39.90734 116.3909
#' # [2,] 39.90734 116.3909
#' # [3,] 39.90734 116.3909
#'
#' ### data.frame
#' df <- data.frame(lat=c(39.908746, 39.908746, 39.908746, NA),
#' lon=c(116.397131, 116.397131, 116.397131, 116.397131))
#' convGCJ2WGS(df) # get
#' # lat lng
#' # [1,] 39.90734 116.3909
#' # [2,] 39.90734 116.3909
#' # [3,] 39.90734 116.3909
#' # [4,] NA NA
#' }
#'
convGCJ2WGS <- function(y, ...){
# Coord Mars GeoSystem (GCJ-02) -> Global GeoSystem (WGS-84)
input <- getCoordArgs(y, ...)
if (! all(abs(input['lat']) <= 90 & abs(input['lon'] <= 180), na.rm=TRUE)){
stop(paste0("Latitude should be within [-90, 90] and longitude ",
"should be within [-180, 180]."))
}
output <- as.data.frame(t(apply(input, MARGIN=1, .gcj2wgs)))
colnames(output) <- c("lat", "lng")
return(output)
}
#' @export
gcj_to_wgs <- convGCJ2WGS
.gcj2wgs <- function(coord, ...){
if (length(coord) > 1){
gcLat <- coord[1]
gcLon <- coord[2]
}else{
gcLat <- coord
gcLon <- unlist(list(...))[1]
}
if (is.na(gcLat) || is.na(gcLon)){
return(c(NA, NA))
}else{
if (! isOutOfChina(gcLat, gcLon)){
coords <- .wgs2gcj(c(gcLat, gcLon))
dLat <- coords[1]
dLon <- coords[2]
GCJ2WGS <- c(2.0 * gcLat - dLat, 2.0 * gcLon - dLon)
}else{
GCJ2WGS <- c(gcLat, gcLon)
}
}
return(GCJ2WGS)
}
#' Transform GCJ-02 (Google CN/Amap) coordinates to BD-09 (Baidu)
#'
#' GCJ-02 is coordinate system mandated by Chinese Gov't. BD-09 is Baidu specific
#' coordinates that encrypts GCJ-02 further more.
#' This function encrypts GCJ-02 into BD-09 coordinates (Baidu coordinates).
#'
#' @note Latitude is the horizontal line serving as y-axis metric, longitude is
#' the vertical line serving as x-axis metric.
#' @author Yiying Wang, \email{wangy@@aetna.com}
#' @param y \itemize{
#' \item A vector \code{c(latitude, longitude)} \cr
#' \item simply latitude \cr
#' \item a matrix (row 1-2 or col 1-2). The function will choose how to read the data \cr
#' \item a data.frame (col 1-2)
#' }
#' @param ... \itemize{
#' \item When \code{y} is only latitude, you can pass in \code{x} (longitude) here. \cr
#' \item when \code{y} is a vector of \code{c(lat, lon)}, you can pass in the rest vectors as well.
#' \item when \code{y} is a matrix or a data.frame, ... is omitted.
#' }
#'
#' @seealso \code{\link{convBD2GCJ}}, \code{\link{convCoord}}
#' @references
#' \url{https://on4wp7.codeplex.com/SourceControl/changeset/view/21483#353936}
#' @return A 2-col data.frame ([lng, lat]) of transformed coordinates.
#' @export
#' @aliases gcj_to_bd
#'
#' @examples
#' \dontrun{
#' # Tiananmen square's GCJ-02 coordinate is c(39.908746, 116.397131)
#' #http://api.map.baidu.com/marker?location=39.91509,116.40350&title=Tiananmen&
#' content=Tiananmen%20square&output=html
#'
#' ## Single point
#' convGCJ2BD(c(39.908746, 116.397131)) # or
#' convGCJ2BD(39.908746, 116.397131) # get
#' # lat lng
#' # [1,] 39.91509 116.4035
#'
#' ## Multiple points
#' ### Vectors
#' convGCJ2BD(c(39.908746, 116.397131), c(39.908746, 116.397131)) # get
#' # lat lng
#' # [1,] 39.91509 116.4035
#' # [2,] 39.91509 116.4035
#'
#' ### Matrix
#' m <- matrix(c(39.908746, 116.397131, 39.908746, 116.397131, 39.908746, 116.397131),
#' nrow=2)
#' m
#' # [,1] [,2] [,3]
#' # [1,] 39.90875 39.90875 39.90875
#' # [2,] 116.39713 116.39713 116.39713
#' convGCJ2BD(m) # get
#' # lat lng
#' # [1,] 39.91509 116.4035
#' # [2,] 39.91509 116.4035
#' # [3,] 39.91509 116.4035
#'
#' ### data.frame
#' df <- data.frame(lat=c(39.908746, 39.908746, 39.908746, NA),
#' lon=c(116.397131, 116.397131, 116.397131, 116.397131))
#' convGCJ2BD(df) # get
#' # lat lng
#' # [1,] 39.91509 116.4035
#' # [2,] 39.91509 116.4035
#' # [3,] 39.91509 116.4035
#' # [4,] NA NA
#' }
#'
convGCJ2BD <- function(y, ...){
# Coord Mars GeoSystem (GCJ-02) -> Baidu GeoSystem (BD-09)
input <- getCoordArgs(y, ...)
if (! all(abs(input['lat']) <= 90 & abs(input['lon'] <= 180), na.rm=TRUE)){
stop(paste0("Latitude should be within [-90, 90] and longitude ",
"should be within [-180, 180]."))
}
output <- as.data.frame(t(apply(input, MARGIN=1, .gcj2bd)))
colnames(output) <- c("lat", "lng")
return(output)
}
#' @export
gcj_to_bd <- convGCJ2BD
.gcj2bd <- function(coord, ...){
XM_PI <- aseshms_env$XM_PI
if (length(coord) > 1){
gcLat <- coord[1]
gcLon <- coord[2]
}else{
gcLat <- coord
gcLon <- unlist(list(...))[1]
}
if (is.na(gcLat) || is.na(gcLon)){
return(c(NA, NA))
}else{
x <- gcLon
y <- gcLat
z <- sqrt(x ** 2 + y ** 2) + 0.00002 * sin(y * XM_PI)
theta <- atn2(y, x) + 0.000003 * cos(x * XM_PI)
GCJ2BD <- c(z * sin(theta) + 0.006, z * cos(theta) + 0.0065)
return(GCJ2BD)
}
}
#' Transform BD-09 (Baidu) coordinates to GCJ-02 (Google CN/Amap)
#'
#' GCJ-02 is coordinate system mandated by Chinese Gov't. BD-09 is Baidu specific
#' coordinates that encrypts GCJ-02 further more.
#' This function decrypts BD-09 back to GCJ-02 coordinates (Chinese coordinates).
#'
#' @note Latitude is the horizontal line serving as y-axis metric, longitude is
#' the vertical line serving as x-axis metric.
#' @author Yiying Wang, \email{wangy@@aetna.com}
#' @param y \itemize{
#' \item A vector \code{c(latitude, longitude)} \cr
#' \item simply latitude \cr
#' \item a matrix (row 1-2 or col 1-2). The function will choose how to read the data \cr
#' \item a data.frame (col 1-2)
#' }
#' @param ... \itemize{
#' \item When \code{y} is only latitude, you can pass in \code{x} (longitude) here. \cr
#' \item when \code{y} is a vector of \code{c(lat, lon)}, you can pass in the rest vectors as well.
#' \item when \code{y} is a matrix or a data.frame, ... is omitted.
#' }
#'
#' @seealso \code{\link{convBD2GCJ}}, \code{\link{convCoord}}.
#' @references
#' \url{https://on4wp7.codeplex.com/SourceControl/changeset/view/21483#353936}
#'
#' @return A 2-col data.frame ([lng, lat]) of transformed coordinates.
#' @export
#' @aliases bd_to_gcj
#'
#' @examples
#' \dontrun{
#' # Tiananmen square's BD-06 coordinate is c(39.91509, 116.40350)
#' # http://www.google.cn/maps/place/Tiananmen,+Dongcheng,+Beijing/@39.90875,116.39713,16z?hl=en
#'
#' ## Single point
#' convBD2GCJ(c(39.91509, 116.40350)) # or
#' convBD2GCJ(39.91509, 116.40350) # get
#' # lat lng
#' # [1,] 39.90875 116.3971
#'
#' ## Multiple points
#' ### Vectors
#' convBD2GCJ(c(39.91509, 116.40350), c(39.91509, 116.40350)) # get
#' # lat lng
#' # [1,] 39.90875 116.3971
#' # [2,] 39.90875 116.3971
#'
#' ### Matrix
#' m <- matrix(c(39.91509, 116.40350, 39.91509, 116.40350, 39.91509, 116.40350), nrow=2)
#' m
#' # [,1] [,2] [,3]
#' # [1,] 39.91509 39.91509 39.91509
#' # [2,] 116.40350 116.40350 116.40350
#' convBD2GCJ(m) # get
#' # lat lng
#' # [1,] 39.90875 116.3971
#' # [2,] 39.90875 116.3971
#' # [3,] 39.90875 116.3971
#'
#' ### data.frame
#' df <- data.frame(lat=c(39.91509, 39.91509, 39.91509, NA),
#' lon=c(116.40350, 116.40350, 116.40350, 116.40350))
#' convBD2GCJ(df) # get
#' # lat lng
#' # [1,] 39.90875 116.3971
#' # [2,] 39.90875 116.3971
#' # [3,] 39.90875 116.3971
#' # [4,] NA NA
#' }
#'
convBD2GCJ <- function(y, ...){
# Coord Baidu GeoSystem (BD-09) -> Mars GeoSystem (GCJ-02)
input <- getCoordArgs(y, ...)
if (! all(abs(input['lat']) <= 90 & abs(input['lon'] <= 180), na.rm=TRUE)){
stop(paste0("Latitude should be within [-90, 90] and longitude ",
"should be within [-180, 180]."))
}
output <- as.data.frame(t(apply(input, MARGIN=1, .bd2gcj)))
colnames(output) <- c("lat", "lng")
return(output)
}
#' @export
bd_to_gcj <- convBD2GCJ
.bd2gcj <- function(coord, ...){
XM_PI <- aseshms_env$XM_PI
if (length(coord) >1){
bdLat <- coord[1]
bdLon <- coord[2]
}else{
bdLat <- coord
bdLon <- unlist(list(...))[1]
}
if (is.na(bdLat) || is.na(bdLon)){
return(c(NA, NA))
}else{
x <- bdLon - 0.0065
y <- bdLat - 0.006
z <- sqrt(x * x + y * y) - 0.00002 * sin(y * XM_PI)
theta <- atn2(y, x) - 0.000003 * cos(x * XM_PI)
BD2GCJ <- c(z * sin(theta), z * cos(theta))
return(BD2GCJ)
}
}
#' Transform WGS-84 (Global GeoSys) coordinates to BD-09 (Baidu)
#'
#' BD-09 is Baidu specific coordinates that encrypts GCJ-02 further more.
#' This function encrypts WGS-84 (Global) into BD-09 coordinates (Baidu coordinates).
#'
#' @note Latitude is the horizontal line serving as y-axis metric, longitude is
#' the vertical line serving as x-axis metric.
#' @author Yiying Wang, \email{wangy@@aetna.com}
#' @param y \itemize{
#' \item A vector \code{c(latitude, longitude)} \cr
#' \item simply latitude \cr
#' \item a matrix (row 1-2 or col 1-2). The function will choose how to read the data \cr
#' \item a data.frame (col 1-2)
#' }
#' @param ... \itemize{
#' \item When \code{y} is only latitude, you can pass in \code{x} (longitude) here. \cr
#' \item when \code{y} is a vector of \code{c(lat, lon)}, you can pass in the rest vectors as well.
#' \item when \code{y} is a matrix or a data.frame, ... is omitted.
#' }
#'
#' @seealso \code{\link{convBD2WGS}}, \code{\link{convWGS2GCJ}}, \code{\link{convCoord}}
#' @references
#' \url{https://on4wp7.codeplex.com/SourceControl/changeset/view/21483#353936}
#' @return A 2-col data.frame ([lng, lat]) of transformed coordinates.
#' @export
#' @aliases wgs_to_bd
#'
#' @examples
#' \dontrun{
#' # Tiananmen square's WGS-84 coordinate is c(39.90734, 116.39089)
#' # http://api.map.baidu.com/marker?location=39.91509,116.40350&title=Tiananmen&content=Tiananmen%20square&output=html
#'
#' ## Single point
#' convWGS2BD(c(39.90734, 116.39089)) # or
#' convWGS2BD(39.90734, 116.39089) # get
#' # lat lng
#' # [1,] 39.91508 116.4035
#'
#' ## Multiple points
#' ### Vectors
#' convWGS2BD(c(39.90734, 116.39089), c(39.90734, 116.39089)) # get
#' # lat lng
#' # [1,] 39.91508 116.4035
#' # [2,] 39.91508 116.4035
#'
#' ### Matrix
#' m <- matrix(c(39.90734, 116.39089, 39.90734, 116.39089, 39.90734, 116.39089), nrow=2)
#' m
#' # [,1] [,2] [,3]
#' # [1,] 39.90734 39.90734 39.90734
#' # [2,] 116.39089 116.39089 116.39089
#' convWGS2BD(m) # get
#' # lat lng
#' # [1,] 39.91508 116.4035
#' # [2,] 39.91508 116.4035
#' # [3,] 39.91508 116.4035
#'
#' ### data.frame
#' df <- data.frame(lat=c(39.90734, 39.90734, 39.90734, NA),
#' lon=c(116.39089, 116.39089, 116.39089, 116.39089))
#' convWGS2BD(df) # get
#' # lat lng
#' # [1,] 39.91508 116.4035
#' # [2,] 39.91508 116.4035
#' # [3,] 39.91508 116.4035
#' # [4,] NA NA
#' }
#'
convWGS2BD <- function(y, ...){
# Global coord (WGS-84) -> Baidu GeoSystem (BD-09)
intermediate <- convWGS2GCJ(y, ...)
return(convGCJ2BD(intermediate))
}
#' @export
wgs_to_bd <- convWGS2BD
#' Transform BD-09 (Baidu) coordinates to WGS-84 (Global Coord)
#'
#' BD-09 is Baidu specific coordinates that encrypts GCJ-02 further more.
#' This function decrypts BD-09 back to WGS-84 coordinates (Global coordinates).
#'
#' @note Latitude is the horizontal line serving as y-axis metric, longitude is
#' the vertical line serving as x-axis metric.
#' @author Yiying Wang, \email{wangy@@aetna.com}
#' @param y \itemize{
#' \item A vector \code{c(latitude, longitude)} \cr
#' \item simply latitude \cr
#' \item a matrix (row 1-2 or col 1-2). The function will choose how to read the data \cr
#' \item a data.frame (col 1-2)
#' }
#' @param ... \itemize{
#' \item When \code{y} is only latitude, you can pass in \code{x} (longitude) here. \cr
#' \item when \code{y} is a vector of \code{c(lat, lon)}, you can pass in the rest vectors as well.
#' \item when \code{y} is a matrix or a data.frame, ... is omitted.
#' }
#'
#' @seealso \code{\link{convWGS2BD}}, \code{\link{convBD2GCJ}}, \code{\link{convCoord}}.
#' @references
#' \url{https://on4wp7.codeplex.com/SourceControl/changeset/view/21483#353936}
#'
#' @return A 2-col data.frame ([lng, lat]) of transformed coordinates.
#' @export
#' @aliases bd_to_wgs
#'
#' @examples
#' \dontrun{
#' # Tiananmen square's BD-06 coordinate is c(39.91509, 116.40350)
#' # http://www.openstreetmap.org/#map=19/39.90734/116.39089
#'
#' ## Single point
#' convBD2WGS(c(39.91509, 116.40350)) # or
#' convBD2WGS(39.91509, 116.40350) # get
#' # lat lng
#' # [1,] 39.90734 116.3909
#'
#' ## Multiple points
#' ### Vectors
#' convBD2WGS(c(39.91509, 116.40350), c(39.91509, 116.40350)) # get
#' # lat lng
#' # [1,] 39.90734 116.3909
#' # [2,] 39.90734 116.3909
#'
#' ### Matrix
#' m <- matrix(c(39.91509, 116.40350, 39.91509, 116.40350, 39.91509, 116.40350), nrow=2)
#' m
#' # [,1] [,2] [,3]
#' # [1,] 39.90734 39.90734 39.90734
#' # [2,] 116.39089 116.39089 116.39089
#' convBD2WGS(m) # get
#' # lat lng
#' # [1,] 39.90734 116.3909
#' # [2,] 39.90734 116.3909
#' # [3,] 39.90734 116.3909
#'
#' ### data.frame
#' df <- data.frame(lat=c(39.91509, 39.91509, 39.91509, NA),
#' lon=c(116.40350, 116.40350, 116.40350, 116.40350))
#' convBD2WGS(df) # get
#' # lat lng
#' # [1,] 39.90734 116.3909
#' # [2,] 39.90734 116.3909
#' # [3,] 39.90734 116.3909
#' # [4,] NA NA
#' }
#'
convBD2WGS <- function(y, ...){
# Coord Baidu GeoSystem (BD-09) -> Global GeoSystem (WGS-84)
intermediate <- convBD2GCJ(y, ...)
return(convGCJ2WGS(intermediate))
}
#' @export
bd_to_wgs <- convBD2WGS
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.