Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting Polylines to GeoJSON

I have a series of (encoded, or decoded) polylines captured from a service like Google Maps / Open Street Maps.

For example:

var polylines = ["kclaG|i_qLe@i@{AgBu@_AsCyCiBmBMMW[eCiC}A_BEEeBiB{@}@MW]a@a@e@]a@IGGG_AgAm@i@MOYYMEQSCCi@k@KKu@y@{A}Ay@cA{@{@eBiBOMe@k@_@a@e@e@QQY[cAkAUWMOUWu@w@AACCYY?AMKUUSSSQ]]GGECCCECA?AAA?A?C?G?WB"
       ,"yfnaGld}pL?e@?]AuDAgA?KAkBGqG?{C?_B?S?aC?[?]A}A?wAASAQ"
       ,"qmnaGlxxpLn@tEL~@"]

I want to store these as GeoJSON. I've found plenty of packages which render GeoJSON through tools like Leaflet, but I'm having trouble finding packages that could export polylines to GeoJSON.

Do any solutions like this exist or is there a particular subset of the GeoJSON standard that I should be looking into so I can write the tool myset?

Side note: I ultimately want a KML or SHP file. I'm planning to use http://ogre.adc4gis.com/ to convert from GeoJSON to SHP.

like image 382
slifty Avatar asked Feb 19 '13 21:02

slifty


People also ask

How do I convert a polyline to a polygon?

The Convert Polylines To Polygon tool is available with the Production Mapping license. With an ArcGIS Desktop Basic license, use the Merge tool and the Auto-Complete Polygon tool to convert polyline features to polygon features.

How do I convert GeoJSON to QGIS?

Paste your code into "Encoded Polyline" and click "Decode". You should then be able to import the resulting GeoJSON into QGis and take it from there!

How do I convert TopoJSON data to GeoJSON?

Please note that your data will not be shared to anybody unless you do it yourself. Upload your TopoJSON data (widely used in software like OpenLayers and Web mapping) and convert them by one click to GeoJSON (JSON) format (widely used in software like MongoDB, GeoServer, CartoWeb and FeatureServer).

How to convert from shp to GeoJSON?

Upload your SHP data (widely used in software like ESRI ArcGIS and ArcView) and convert them by one click to GeoJSON (JSON) format (widely used in software like MongoDB, GeoServer, CartoWeb and FeatureServer). Notice to SHP format - do not forgot to upload also associated .dbf and .shx files (and if available also .prj and .cpg files).


1 Answers

You're looking for the GeoJSON LineString geometry type. Although the algorithm is a little complicated, there is a a project on Github that provides the functionality in JavaScript. You should easily be able to port this to the language of your choosing. I have also wrapped the functionality into a JSFiddle so you can use this as an online tool.

You'll find the tool at https://jsfiddle.net/ivansams/tw7qLvh4/2/ - you can paste an encoded polyline into "Encoded Polyline" and click "Decode", and this will return a GeoJSON LineString. The code is reproduced below because of StackOverflow's rules around requiring JSFiddle to be accompanied by code, but get the up to date code at the Github project site.

function decode() {
  var encodedPolyline = document.getElementById("encoded-polyline").value;
  document.getElementById("geojson").value = encodedPolyline;
  var coords = polyline.toGeoJSON(encodedPolyline);
  document.getElementById("geojson").value = JSON.stringify(coords);
}

var polyline = {};

function encode(current, previous, factor) {
  current = Math.round(current * factor);
  previous = Math.round(previous * factor);
  var coordinate = current - previous;
  coordinate <<= 1;
  if (current - previous < 0) {
    coordinate = ~coordinate;
  }
  var output = '';
  while (coordinate >= 0x20) {
    output += String.fromCharCode((0x20 | (coordinate & 0x1f)) + 63);
    coordinate >>= 5;
  }
  output += String.fromCharCode(coordinate + 63);
  return output;
}

/**
 * Decodes to a [latitude, longitude] coordinates array.
 *
 * This is adapted from the implementation in Project-OSRM.
 *
 * @param {String} str
 * @param {Number} precision
 * @returns {Array}
 *
 * @see https://github.com/Project-OSRM/osrm-frontend/blob/master/WebContent/routing/OSRM.RoutingGeometry.js
 */
polyline.decode = function(str, precision) {
  var index = 0,
    lat = 0,
    lng = 0,
    coordinates = [],
    shift = 0,
    result = 0,
    byte = null,
    latitude_change,
    longitude_change,
    factor = Math.pow(10, precision || 5);

  // Coordinates have variable length when encoded, so just keep
  // track of whether we've hit the end of the string. In each
  // loop iteration, a single coordinate is decoded.
  while (index < str.length) {

    // Reset shift, result, and byte
    byte = null;
    shift = 0;
    result = 0;

    do {
      byte = str.charCodeAt(index++) - 63;
      result |= (byte & 0x1f) << shift;
      shift += 5;
    } while (byte >= 0x20);

    latitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));

    shift = result = 0;

    do {
      byte = str.charCodeAt(index++) - 63;
      result |= (byte & 0x1f) << shift;
      shift += 5;
    } while (byte >= 0x20);

    longitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));

    lat += latitude_change;
    lng += longitude_change;

    coordinates.push([lat / factor, lng / factor]);
  }

  return coordinates;
};

/**
 * Encodes the given [latitude, longitude] coordinates array.
 *
 * @param {Array.<Array.<Number>>} coordinates
 * @param {Number} precision
 * @returns {String}
 */
polyline.encode = function(coordinates, precision) {
  if (!coordinates.length) {
    return '';
  }

  var factor = Math.pow(10, precision || 5),
    output = encode(coordinates[0][0], 0, factor) + encode(coordinates[0][1], 0, factor);

  for (var i = 1; i < coordinates.length; i++) {
    var a = coordinates[i],
      b = coordinates[i - 1];
    output += encode(a[0], b[0], factor);
    output += encode(a[1], b[1], factor);
  }

  return output;
};

function flipped(coords) {
  var flipped = [];
  for (var i = 0; i < coords.length; i++) {
    flipped.push(coords[i].slice().reverse());
  }
  return flipped;
}

/**
 * Encodes a GeoJSON LineString feature/geometry.
 *
 * @param {Object} geojson
 * @param {Number} precision
 * @returns {String}
 */
polyline.fromGeoJSON = function(geojson, precision) {
  if (geojson && geojson.type === 'Feature') {
    geojson = geojson.geometry;
  }
  if (!geojson || geojson.type !== 'LineString') {
    throw new Error('Input must be a GeoJSON LineString');
  }
  return polyline.encode(flipped(geojson.coordinates), precision);
};

/**
 * Decodes to a GeoJSON LineString geometry.
 *
 * @param {String} str
 * @param {Number} precision
 * @returns {Object}
 */
polyline.toGeoJSON = function(str, precision) {
  var coords = polyline.decode(str, precision);
  return {
    type: 'LineString',
    coordinates: flipped(coords)
  };
};

if (typeof module === 'object' && module.exports) {
  module.exports = polyline;
}
like image 157
08Dc91wk Avatar answered Oct 10 '22 22:10

08Dc91wk