Decoding Google Maps API Encoded Overview Polyline with Javascript for use in Mapbox

Have been searching for various JS functions that can decode an encoded polyline to a geoJSON string, and all that I try come up with really odd lat,lng points. Usually starting in the correct location but then wandering way off course.

Here's one of the functions I found at https://github.com/jhermsmeier/node-google-polyline/blob/master/lib/decode.js

    function decode( value ) {

  var values = decode.integers( value )
  var points = []

  for( var i = 0; i < values.length; i += 2 ) {
    points.push([
      ( values[ i + 0 ] += ( values[ i - 2 ] || 0 ) ) / 1e5,
      ( values[ i + 1 ] += ( values[ i - 1 ] || 0 ) ) / 1e5,
    ])
  }

  return points

}

decode.sign = function( value ) {
  return value & 1 ? ~( value >>> 1 ) : ( value >>> 1 )
}

decode.integers = function( value ) {

  var values = []
  var byte = 0
  var current = 0
  var bits = 0

  for( var i = 0; i < value.length; i++ ) {

    byte = value.charCodeAt( i ) - 63
    current = current | (( byte & 0x1F ) << bits )
    bits = bits + 5

    if( byte < 0x20 ) {
      values.push( decode.sign( current ) )
      current = 0
      bits = 0
    }

  }

  return values

}

module.exports = decode

When using this encoded polyline:

{nccIj{`EnIuBdAo@b@g@b@y@To@l@cCf@{BLqA@kClAqRF_@Vk@VSRC`Ij@|QfAj@?TMJKnEcKpAiCbCoF~BoFt@yB`BmFjBkFh@eAb@q@h@e@n@_@h@]RUj@}@h@qA\mAVwA`A{ExBaJvDaKrAqCzA_C|BcEfDyHf@mBr@cEb@kBj@}Bp@uB`FfEh@^nBd@`AF`Bo@d@KxBVZGbEqHhB}ErAaEjBaDd@q@~@y@tAy@l@ORARIZWhAcAo@zGfAPgAQn@{Gf@yCy@]s@o@o@m@mB{Ac@e@k@u@gAkAmBiCkGoHABCBEAAG?IBEB?Fa@tAmDdAqCX{@Zq@dB{E~AcE`C{FfDoIdBiEp@cC|@mCl@cB~@}BaCqCgAiASMq@SMIKMIOIg@OuBW{INmKAgAGy@McASw@}A{Dq@eBSs@Q_AKmAIyACeDLoPQgHFaE^oKZ}DfA}IVaCDw@AcBEo@Ki@k@iBGe@Es@CyEAqECaEJoC~@yIRcFHgEMyHOyFUoEWaHI}@UsAc@qA[o@[a@MQiB{Ac@_@aB{AYe@CODm@Nq@VcAJe@DcAF_BBmGDaC@_BGwAOcCSqA]}@_C}DqA_CiAeCaA}B}@}BSs@Oy@WuCEwA@mAJeGAy@OiAS}@Yo@gD}FaH{LyEyHy@yA_AuBWs@c@sBYqBIgAIkBOeIWaHM}ASa@MQH[dCiIl@oBhEuLfEkL~AeEn@sA~BuE~BuE~@qBp@}Bd@yB`@wCTyCF_B@gEE{BU}CUmBg@sC[_BW}@]y@qB_E{A{B{@kAk@s@[WcC}AmA{@gBgBkPmRsDiE}BiDQQ]U{C{AU[EKE]?s@L_Ar@iDZaC`AiGLqABs@?yDDmBFQFEXCt@ApC[jBOjABfCR\?PEPKVYXo@bBsGbDiJX}@l@iCr@qC|@uCZu@j@{@hCgDfHeIn@aA^q@v@kBRw@^cBt@uF|AmL^{CRgCHmBDoBCaEMoCQqBUeB[cB]{A[gA}@eC]cAMq@M}@GeBEiA@i@VkBBg@?m@EQCY@w@DYR[RMRARFTD\ALGv@k@hBqA~BsAfGiDrCsBn@c@?AA??AAA?C@EBA@@@@?@XST[Rm@\eAhA}DJ{@Ro@?IBQFGHCFBDH@FJH^f@^f@bFjJd@|@RVRDLEJI\}@ZmAX_BL_AT_B`@kCj@iDF_@HONSVAL@D@TWj@o@`@_@dAyAVg@n@}A`BaFR_ATJtBx@HJXl@bD~AHaAFYXm@JkAFiA

which is based in the UK, I get this collection of lat/lng positions:

"[[53.10718,-0.9927],[53.1055,-0.99211],[53.10515,-0.99187],[53.10497,-0.99167],[53.10479,-0.99138],[53.10468,-0.99114],[53.10445,-0.99048],[53.10425,-0.98986],[53.10418,-0.98945],[53.10417,-0.98875],[53.10378,-0.98562],[53.10374,-0.98546],[53.10362,-0.98524],[53.1035,-0.98514],[53.1034,-0.98512],[53.10179,-0.98534],[53.09876,-0.9857],[53.09854,-0.9857],[53.09843,-0.98563],[53.09837,-0.98557],[53.09733,-0.98363],[53.09692,-0.98294],[53.09626,-0.98174],[53.09562,-0.98054],[53.09535,-0.97993],[53.09486,-0.97874],[53.09432,-0.97756],[53.09411,-0.97721],[53.09393,-0.97696],[53.09372,-0.97677],[53.09348,-0.97661],[53.09327,-0.97646],[53.09317,-0.97635],[53.09295,-0.97604],[53.09274,-0.97563],[53.09313,-0.97575],[53.09357,-0.97608],[53.09467,-0.97669],[53.09644,-0.97761],[53.09837,-0.97803],[53.0991,-0.97849],[53.09974,-0.97912],[53.10072,-0.97996],[53.10229,-0.98016],[53.10284,-0.98042],[53.10382,-0.9806],[53.10436,-0.98082],[53.10499,-0.98107],[53.10558,-0.9822],[53.10458,-0.98241],[53.10442,-0.98297],[53.10423,-0.9833],[53.10419,-0.98379],[53.10443,-0.98398],[53.10449,-0.98459],[53.10437,-0.98473],[53.10441,-0.98571],[53.10594,-0.98624],[53.10705,-0.98666],[53.10802,-0.9872],[53.10883,-0.98739],[53.10908,-0.98771],[53.10937,-0.98814],[53.10966,-0.98837],[53.10974,-0.98847],[53.10975,-0.98857],[53.1098,-0.98871],[53.10992,-0.98908],[53.11026,-0.98884],[53.10884,-0.9892],[53.10875,-0.98884],[53.10884,-0.98908],[53.11026,-0.98928],[53.11103,-0.98899],[53.11118,-0.98873],[53.11142,-0.98849],[53.11165,-0.98794],[53.11211,-0.98776],[53.1123,-0.98754],[53.11257,-0.98718],[53.11295,-0.98663],[53.11364,-0.98529],[53.11516,-0.98528],[53.11514,-0.98526],[53.11512,-0.98523],[53.11513,-0.98522],[53.11517,-0.98522],[53.11522,-0.98524],[53.11525,-0.98526],[53.11525,-0.9853],[53.11542,-0.98573],[53.11629,-0.98608],[53.11702,-0.98621],[53.11732,-0.98635],[53.11757,-0.98686],[53.11867,-0.98734],[53.11965,-0.98799],[53.12091,-0.98883],[53.12259,-0.98934],[53.1236,-0.98959],[53.12426,-0.9899],[53.12497,-0.99013],[53.12547,-0.99045],[53.1261,-0.9898],[53.12683,-0.98944],[53.1272,-0.98934],[53.12727,-0.98909],[53.12737,-0.98902],[53.12742,-0.98896],[53.12749,-0.98891],[53.12757,-0.98886],[53.12777,-0.98878],[53.12836,-0.98866],[53.1301,-0.98874],[53.13209,-0.98873],[53.13245,-0.98869],[53.13274,-0.98862],[53.13308,-0.98852],[53.13336,-0.98805],[53.1343,-0.9878],[53.13481,-0.9877],[53.13507,-0.98761],[53.13539,-0.98755],[53.13578,-0.9875],[53.13623,-0.98748],[53.13706,-0.98755],[53.13986,-0.98746],[53.14134,-0.9875],[53.14231,-0.98766],[53.14431,-0.9878],[53.14526,-0.98816],[53.14701,-0.98828],[53.14766,-0.98831],[53.14794,-0.9883],[53.14844,-0.98827],[53.14868,-0.98821],[53.14889,-0.98799],[53.14942,-0.98795],[53.14961,-0.98792],[53.14987,-0.9879],[53.15096,-0.98789],[53.15201,-0.98787],[53.15298,-0.98793],[53.1537,-0.98825],[53.15543,-0.98835],[53.15657,-0.9884],[53.15757,-0.98833],[53.15914,-0.98825],[53.16039,-0.98814],[53.16143,-0.98802],[53.16288,-0.98797],[53.16319,-0.98786],[53.16361,-0.98768],[53.16402,-0.98754],[53.16426,-0.9874],[53.16443,-0.98733],[53.16452,-0.9868],[53.16498,-0.98662],[53.16514,-0.98613],[53.1656,-0.986],[53.16579,-0.98598],[53.16587,-0.98601],[53.1661,-0.98609],[53.16635,-0.98621],[53.16669,-0.98627],[53.16688,-0.9863],[53.16722,-0.98634],[53.1677,-0.98636],[53.16905,-0.98639],[53.1697,-0.9864],[53.17018,-0.98636],[53.17062,-0.98628],[53.17128,-0.98618],[53.17169,-0.98603],[53.172,-0.98539],[53.17295,-0.98498],[53.17359,-0.98461],[53.17426,-0.98428],[53.17489,-0.98397],[53.17552,-0.98387],[53.17578,-0.98379],[53.17607,-0.98367],[53.17682,-0.98364],[53.17726,-0.98365],[53.17765,-0.98371],[53.17896,-0.9837],[53.17925,-0.98362],[53.17962,-0.98352],[53.17993,-0.98339],[53.18017,-0.98255],[53.18144,-0.9811],[53.18366,-0.98001],[53.18523,-0.97972],[53.18568,-0.9794],[53.18627,-0.97928],[53.18653,-0.9791],[53.18711,-0.97897],[53.18768,-0.97892],[53.18804,-0.97887],[53.18858,-0.97879],[53.19021,-0.97867],[53.19166,-0.9786],[53.19213,-0.9785],[53.1923,-0.97843],[53.19239,-0.97848],[53.19253,-0.97915],[53.19418,-0.97938],[53.19474,-0.98039],[53.19693,-0.98139],[53.19907,-0.98187],[53.20006,-0.98211],[53.20048,-0.98275],[53.20155,-0.98339],[53.20262,-0.98371],[53.20319,-0.98396],[53.20382,-0.98415],[53.20443,-0.98432],[53.20519,-0.98443],[53.20596,-0.98447],[53.20644,-0.98448],[53.20744,-0.98445],[53.20806,-0.98434],[53.20885,-0.98423],[53.2094,-0.98403],[53.21014,-0.98389],[53.21062,-0.98377],[53.21093,-0.98362],[53.21122,-0.98305],[53.21218,-0.98259],[53.2128,-0.98229],[53.21318,-0.98207],[53.21344,-0.98193],[53.21356,-0.98127],[53.21403,-0.98088],[53.21433,-0.98036],[53.21485,-0.97758],[53.21796,-0.97668],[53.21897,-0.97605],[53.21982,-0.97596],[53.21991,-0.97581],[53.22002,-0.97503],[53.22048,-0.97492],[53.22062,-0.97489],[53.22068,-0.97486],[53.22083,-0.97486],[53.22109,-0.97493],[53.22141,-0.97519],[53.22226,-0.97533],[53.22291,-0.97566],[53.22424,-0.97573],[53.22465,-0.97575],[53.22491,-0.97575],[53.22584,-0.97578],[53.22639,-0.97582],[53.22648,-0.97586],[53.22651,-0.97599],[53.22653,-0.97626],[53.22654,-0.97699],[53.22668,-0.97753],[53.22676,-0.97791],[53.22674,-0.97859],[53.22664,-0.97859],[53.22655,-0.97856],[53.22646,-0.9785],[53.22634,-0.97837],[53.22621,-0.97813],[53.22571,-0.97675],[53.22489,-0.97494],[53.22476,-0.97463],[53.22453,-0.97394],[53.22427,-0.97321],[53.22396,-0.97246],[53.22382,-0.97219],[53.2236,-0.97189],[53.22291,-0.97105],[53.22143,-0.96942],[53.22119,-0.96909],[53.22103,-0.96884],[53.22075,-0.9683],[53.22065,-0.96802],[53.22049,-0.96752],[53.22022,-0.96629],[53.21975,-0.96414],[53.21959,-0.96336],[53.21949,-0.96268],[53.21944,-0.96213],[53.21941,-0.96157],[53.21943,-0.9606],[53.2195,-0.95988],[53.21959,-0.95931],[53.2197,-0.9588],[53.21984,-0.9583],[53.21999,-0.95784],[53.22013,-0.95748],[53.22044,-0.95681],[53.22059,-0.95647],[53.22066,-0.95622],[53.22073,-0.95591],[53.22077,-0.9554],[53.2208,-0.95503],[53.22079,-0.95482],[53.22067,-0.95428],[53.22065,-0.95408],[53.22065,-0.95385],[53.22068,-0.95376],[53.2207,-0.95363],[53.22069,-0.95335],[53.22066,-0.95322],[53.22056,-0.95308],[53.22046,-0.95301],[53.22036,-0.953],[53.22026,-0.95304],[53.22015,-0.95307],[53.22016,-0.95314],[53.2202,-0.95342],[53.22042,-0.95395],[53.22083,-0.95459],[53.22125,-0.95591],[53.2221,-0.95665],[53.22268,-0.95689],[53.22286,-0.95689],[53.22287,-0.95688],[53.22287,-0.95688],[53.22288,-0.95687],[53.22289,-0.95687],[53.22291,-0.95688],[53.22294,-0.9569],[53.22295,-0.95691],[53.22294,-0.95692],[53.22293,-0.95692],[53.22292,-0.95705],[53.22302,-0.95716],[53.22316,-0.95726],[53.22339,-0.95691],[53.22302,-0.95596],[53.22296,-0.95566],[53.22286,-0.95542],[53.22286,-0.95537],[53.22284,-0.95528],[53.2228,-0.95524],[53.22275,-0.95522],[53.22271,-0.95524],[53.22268,-0.95529],[53.22267,-0.95533],[53.22261,-0.95538],[53.22245,-0.95558],[53.22229,-0.95578],[53.22115,-0.9576],[53.22096,-0.95791],[53.22086,-0.95803],[53.22076,-0.95806],[53.22069,-0.95803],[53.22063,-0.95798],[53.22094,-0.95812],[53.22133,-0.95825],[53.22181,-0.95832],[53.22213,-0.95843],[53.22261,-0.9586],[53.22331,-0.95882],[53.22416,-0.95886],[53.22432,-0.95891],[53.2244,-0.95899],[53.2245,-0.95911],[53.22451,-0.95918],[53.2245,-0.95921],[53.22449,-0.95932],[53.22461,-0.95954],[53.22485,-0.95971],[53.22501,-0.96006],[53.22546,-0.96018],[53.22566,-0.96042],[53.22613,-0.96091],[53.22726,-0.96101],[53.22758,-0.96112],[53.22752,-0.96171],[53.22723,-0.96176],[53.22717,-0.96189],[53.22694,-0.96271],[53.22646,-0.96276],[53.22679,-0.9628],[53.22692,-0.96293],[53.22715,-0.96299],[53.22753,-0.96303],[53.2279,null]]


"

The result (using this website: https://developers.google.com/maps/documentation/utilities/polylineutility) is very different when plotted - and is the correct path.

Any help appreciated.

Thanks


Solution 1:

Leaflet.encoded plugin supports to encode to and decode from Google maps polyline encoding, here is the example for provided encoded path

Note: backslashes \ in the provided encoded string needs to be escaped overwise it will be interpreted as escape character. The encoded path has been updated accordingly

Example

var encoded = "{nccIj{`EnIuBdAo@b@g@b@y@To@l@cCf@{BLqA@kClAqRF_@Vk@VSRC`Ij@|QfAj@?TMJKnEcKpAiCbCoF~BoFt@yB`BmFjBkFh@eAb@q@h@e@n@_@h@]RUj@}@h@qA\\mAVwA`A{ExBaJvDaKrAqCzA_C|BcEfDyHf@mBr@cEb@kBj@}Bp@uB`FfEh@^nBd@`AF`Bo@d@KxBVZGbEqHhB}ErAaEjBaDd@q@~@y@tAy@l@ORARIZWhAcAo@zGfAPgAQn@{Gf@yCy@]s@o@o@m@mB{Ac@e@k@u@gAkAmBiCkGoHABCBEAAG?IBEB?Fa@tAmDdAqCX{@Zq@dB{E~AcE`C{FfDoIdBiEp@cC|@mCl@cB~@}BaCqCgAiASMq@SMIKMIOIg@OuBW{INmKAgAGy@McASw@}A{Dq@eBSs@Q_AKmAIyACeDLoPQgHFaE^oKZ}DfA}IVaCDw@AcBEo@Ki@k@iBGe@Es@CyEAqECaEJoC~@yIRcFHgEMyHOyFUoEWaHI}@UsAc@qA[o@[a@MQiB{Ac@_@aB{AYe@CODm@Nq@VcAJe@DcAF_BBmGDaC@_BGwAOcCSqA]}@_C}DqA_CiAeCaA}B}@}BSs@Oy@WuCEwA@mAJeGAy@OiAS}@Yo@gD}FaH{LyEyHy@yA_AuBWs@c@sBYqBIgAIkBOeIWaHM}ASa@MQH[dCiIl@oBhEuLfEkL~AeEn@sA~BuE~BuE~@qBp@}Bd@yB`@wCTyCF_B@gEE{BU}CUmBg@sC[_BW}@]y@qB_E{A{B{@kAk@s@[WcC}AmA{@gBgBkPmRsDiE}BiDQQ]U{C{AU[EKE]?s@L_Ar@iDZaC`AiGLqABs@?yDDmBFQFEXCt@ApC[jBOjABfCR\\?PEPKVYXo@bBsGbDiJX}@l@iCr@qC|@uCZu@j@{@hCgDfHeIn@aA^q@v@kBRw@^cBt@uF|AmL^{CRgCHmBDoBCaEMoCQqBUeB[cB]{A[gA}@eC]cAMq@M}@GeBEiA@i@VkBBg@?m@EQCY@w@DYR[RMRARFTD\\ALGv@k@hBqA~BsAfGiDrCsBn@c@?AA??AAA?C@EBA@@@@?@XST[Rm@\\eAhA}DJ{@Ro@?IBQFGHCFBDH@FJH^f@^f@bFjJd@|@RVRDLEJI\\}@ZmAX_BL_AT_B`@kCj@iDF_@HONSVAL@D@TWj@o@`@_@dAyAVg@n@}A`BaFR_ATJtBx@HJXl@bD~AHaAFYXm@JkAFiA";
var coordinates = L.Polyline.fromEncoded(encoded).getLatLngs();
//console.log(coordinates);


var map = L.map('map').setView([53.07,-0.85], 11);
L.tileLayer(
    'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        maxZoom: 18,
    }).addTo(map);

var polyline = L.polyline(
    coordinates,
    {
        color: 'red',
        weight: 10,
        opacity: .7,
        dashArray: '20,15',
        lineJoin: 'round'
    }
).addTo(map);
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
<script type="text/javascript" src="https://rawgit.com/jieter/Leaflet.encoded/master/Polyline.encoded.js"></script>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
<div id="map" style="width: 600px; height: 400px"></div>
<script type="text/javascript" src="app.js"></script>"

Solution 2:

You will need to swap the coordinates elements to [longitude, latitude]

The Google order of coordinates is latitude/longitude pairs.

GeoJSON is in the order of longitude and latitude.

For example

points.push([  //                        |<- change is in this column
      ( values[ i + 1 ] += ( values[ i - 1 ] || 0 ) ) / 1e5,
      ( values[ i + 0 ] += ( values[ i - 2 ] || 0 ) ) / 1e5,

    ])

User @tmcw has an excellent resource regarding the differences

  • http://www.macwright.org/lonlat/

http://www.macwright.org/lonlat/)