I used the distm() function in the geosphere package to calculate the distance when points and vertices are represented in the coordinate system. In addition, you can easily do some interlacing by substituting dis <- function(x0,x1,y0,y1){sqrt((x0-x1)^2 +(y0-y1)^2)} for distm() .
algo.p2poly <- function(pt, poly){ if(!identical(poly[1,],poly[nrow(poly),])){poly<-rbind(poly,poly[1,])} library(geosphere) n <- nrow(poly) - 1 pa <- distm(pt, poly[1:n, ]) pb <- distm(pt, poly[2:(n+1), ]) ab <- diag(distm(poly[1:n, ], poly[2:(n+1), ])) p <- (pa + pb + ab) / 2 d <- 2 * sqrt(p * (p - pa) * (p - pb) * (p - ab)) / ab cosa <- (pa^2 + ab^2 - pb^2) / (2 * pa * ab) cosb <- (pb^2 + ab^2 - pa^2) / (2 * pb * ab) d[which(cosa <= 0)] <- pa[which(cosa <= 0)] d[which(cosb <= 0)] <- pb[which(cosb <= 0)] return(min(d)) }
Example:
poly <- matrix(c(114.33508, 114.33616, 114.33551, 114.33824, 114.34629, 114.35053, 114.35592, 114.35951, 114.36275, 114.35340, 114.35391, 114.34715, 114.34385, 114.34349, 114.33896, 114.33917, 30.48271, 30.47791, 30.47567, 30.47356, 30.46876, 30.46851, 30.46882, 30.46770, 30.47219, 30.47356, 30.47499, 30.47673, 30.47405, 30.47723, 30.47872, 30.48320), byrow = F, nrow = 16) pt1 <- c(114.33508, 30.48271) pt2 <- c(114.6351, 30.98271) algo.p2poly(pt1, poly) algo.p2poly(pt2, poly)
Result:
> algo.p2poly(pt1, poly) [1] 0 > algo.p2poly(pt2, poly) [1] 62399.81