Last active
January 22, 2018 22:03
-
-
Save serialc/3a8ab85df9eb0cec7177f2b4bd13a1cd to your computer and use it in GitHub Desktop.
A google maps points decoder function in R
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Decode Google encoding lat,long point series | |
# Based on JavaScript code by Mapbox on Github: https://github.com/mapbox/polyline/blob/master/src/polyline.js | |
# Google algorithm: http://code.google.com/apis/maps/documentation/polylinealgorithm.html | |
decode_google_path <- function( point_string ) { | |
# break string into individual characters | |
chars <- strsplit(point_string, '')[[1]] | |
# get the utf8 integer representation of that character | |
# only characters from 64 onwards are used (@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~) | |
value <- sapply(chars, utf8ToInt) - 63 | |
# Those values smaller than 32 (0x20 in hexadecimal) are the end of a lat or long data piece | |
# define groups | |
groups <- cumsum( !bitwAnd(value, 0x20) != 0 ) | |
# need to shift the group delimiter back by one and drop the last value to be aligned properly | |
groups <- c(0, groups[-length(groups)]) | |
# group lat/lngs together | |
llpair <- as.integer(groups/2) | |
# get the five right-most bits only of values | |
value <- bitwAnd(value, 0x1F) | |
# go through each lat/lng pair and 'stack' multiple integers into individual lat and long values | |
latlng <- data.frame(t(sapply(split(data.frame(value, groups), llpair), function(ll) { | |
# separately process the lat and long (in the same way) | |
result <- sapply( split(ll$value, ll$groups), function(l) { | |
# each value refers to a different magnitude that are all summed | |
sum(bitwShiftL(l, 0:(length(l) - 1) * 5)) | |
}) | |
# odd number require a different operation | |
odd <- sapply(result, bitwAnd, b=1) == 1 | |
# if odd, shift bits right (divide by 2) and invert all bits (make negative and -1) | |
result[odd] <- bitwNot(bitwShiftR(result[odd], 1)) | |
# if even, shift bits right (divide by 2) | |
result[!odd] <- bitwShiftR(result[!odd], 1) | |
result/10^5 | |
}))) | |
path <- sapply(latlng, cumsum) | |
colnames(path) <- c('lat', 'lng') | |
return(path) | |
} | |
# small test (6 lat, long pairs) | |
decode_google_path("qchrHadg]\\?^FtBVfCEfGuA") | |
# big test (313 lat, long pairs) | |
decode_google_path("cw_sHehu\\^Bl@D`@JbA^t@P~ANSnBgBlKgKE{CKIwDHsAZuCL{@ASHcACc@qAyGUwAAMDEDQFi@Ac@Gc@K[GI?MGSQ_@G[AyBEg@BaBr@yFnAcHj@aClB_HhCeJXWp@sAp@iABe@As@QiF]yIKsFW}HI{DDa@DQAg@EOIMSqFWkIG{B[wGa@uFc@gFu@oGk@cDi@aCWeAy@cC_AiB{DoGyIuN}DqGuCqEAE?CCECC@QMe@COIIE?MWMI][gKiQuA_CBM@YAWM_@IKECD[HS~GsFtBcCfAgAd@c@v@aAlOkJtG{DxIoFdFwCjKkGtA}@v@i@|CgBlI}ErTiMxGaEjLsHvCqBpF{DhIkG|JaIf\\gXpHcGjGeEbH_EzC{ArCsAlGgCzFoBhCu@tEiArJsBjXaGhEaAVJL?vQkBtAKhD]PGd@jAhAfCV^`EhDn@f@DRNTPL?D?H@HDNJHJ?JIFO@UAIN_@DQdB}Cz@}AdFaJrCaF`D{FxF_LpTka@b@g@vBuDnFyJjBiDdIcO|IgPvAaCrD_HjE_I~GcMhCiElBmDb@?|c@TxDAbFq@hBa@fZqIjAc@f@Kj@Eb@Bh@T`Ap@`KxHzCxBrAn@f@JvAj@xBfAlAb@dA`@bBf@z@Cf@I`@O^c@xA}Al@g@`@QpD{@AQrDwAL`@P^PTPH|@NPBNHVh@PdA\\fCTrATx@P`@Hn@@HDDB?FADKd@GxBBd@CxCo@fAWz@Cx@BzBNpCQxEo@PGnBmAnCgC~@aALA~@Hn@`@nCfD\\Zr@XbIhBv@L^BpBC`HCz@JtBpBhA|@d@HvES\\Bn@HnDdA^Dh@?l@Nt@l@f@j@d@`@^Rv@P~@@tAKv@Fp@Vv@`@h@lCV~@\\d@rBjBZFjCxBzB~A\\J`BFjFAx@O`@C|Bh@`AGl@Gd@S\\]RUd@Wp@WT?D?BFDJ?RGrBFpAHTf@p@z@dCvApEzAlENJlAKzCJRFJJFJ@XUx@\\?^FtBVfCEfGuA") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment