Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 863
Neil Simpson Avatar asked Nov 19 '16 14:11

Neil Simpson


3 Answers

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>"
like image 155
Vadim Gremyachev Avatar answered Nov 11 '22 08:11

Vadim Gremyachev


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/)

like image 22
RobLabs Avatar answered Nov 11 '22 07:11

RobLabs


Mapbox polyline is another library that can do it for you.

Encodes from / decodes into [lat, lng] coordinate pairs. Use fromGeoJSON() to encode from GeoJSON objects, or toGeoJSON to decode to a GeoJSON LineString.

Example

var polyline = require('@mapbox/polyline');

// returns an array of lat, lon pairs
polyline.decode('_p~iF~ps|U_ulLnnqC_mqNvxq`@');

// returns an array of lat, lon pairs from polyline6 by passing a precision parameter
polyline.decode('cxl_cBqwvnS|Dy@ogFyxmAf`IsnA|CjFzCsHluD_k@hi@ljL', 6);

// returns a GeoJSON LineString feature
polyline.toGeoJSON('_p~iF~ps|U_ulLnnqC_mqNvxq`@');

// returns a string-encoded polyline (from coordinate ordered lat,lng)
polyline.encode([[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]]);

// returns a string-encoded polyline from a GeoJSON LineString
polyline.fromGeoJSON({ "type": "Feature",
  "geometry": {
    "type": "LineString",
    "coordinates": [[-120.2, 38.5], [-120.95, 40.7], [-126.453, 43.252]]
  },
  "properties": {}
});

console.log(polyline.decode('_p~iF~ps|U_ulLnnqC_mqNvxq`@'));
<script src="https://cdn.jsdelivr.net/npm/@mapbox/[email protected]/src/polyline.min.js"></script>
like image 1
Pavel Chuchuva Avatar answered Nov 11 '22 08:11

Pavel Chuchuva