Skip to content

Instantly share code, notes, and snippets.

@blemoine
Created September 9, 2015 10:07

Revisions

  1. blemoine created this gist Sep 9, 2015.
    119 changes: 119 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,119 @@
    /*
    pour lancer :
    node geoJsonMinifier.js <cheminDuFichierGeoJson> > <cheminDuFichierDeSorti>

    */

    var fs = require('fs');
    var _ = require('lodash');

    var geoJsonPath = process.argv[2];
    if (!geoJsonPath) {
    console.error("You must pass a path to a geoJson file", geoJsonPath);
    return;
    }
    fs.readFile(geoJsonPath, function (err, geoJsonContent) {
    if (err) {
    console.error("Error while reading file", err);
    return;
    }

    var geoJson = JSON.parse(geoJsonContent);

    if (geoJson.type != 'FeatureCollection') {
    console.error("The type of the geoJsonContent must be FeatureCollection", geoJson.type);
    return;
    }

    console.log(JSON.stringify(minifyGeoJson(geoJson)));
    });

    function minifyGeoJson(geoJson) {

    var minifiedFeatures = geoJson.features.map(function (feature) {
    var minifyCoordinate = _.flow(decreasePrecision(3), removeDuplicatePoint);
    var newCoordinates = minifyCoordinate(feature.geometry.coordinates);

    return {
    "type": "Feature",
    "id": feature.id,
    "properties": feature.properties,
    "geometry": {
    "type": feature.geometry.type,
    "coordinates": newCoordinates
    }
    };
    });

    return {
    "type": "FeatureCollection",
    "features": minifiedFeatures
    }
    }

    function isCoordinate(maybeCoordinates) {
    return _.isArray(maybeCoordinates) && maybeCoordinates.length == 2 && _.isNumber(maybeCoordinates[0]) && _.isNumber(maybeCoordinates[1])
    }

    function removeDuplicatePoint(arr) {
    var arrSize = arr.length;
    return arr.map(function(el) {
    if(_.isArray(el) ) {
    if(el.every(isCoordinate)) {
    var elSize = el.length;
    return el.filter(function(coordinates, idx) {
    //Minus 2 beacause we want at least 3 points
    if(idx > 0 && idx < elSize - 2) {
    return distanceBetweenCoordinates(coordinates, el[idx - 1]) > 100
    } else {
    return true;
    }
    });
    } else {
    return removeDuplicatePoint(el);
    }
    } else {
    return el;
    }
    })
    }

    function decreasePrecision(precision) {
    return function _decreasePrecision(arr) {
    var tenFactor = Math.pow(10, precision);

    return arr.map(function (el) {
    if (_.isArray(el)) {
    return _decreasePrecision(el);
    } else if (_.isNumber(el)) {
    return Math.round(el * tenFactor) / tenFactor;
    } else {
    return el;
    }
    })
    }
    }

    function toRadians(n) {
    return n * Math.PI / 180;
    }

    function distanceBetweenCoordinates(coord1, coord2) {
    var lon1 = coord1[0];
    var lat1 = coord1[1];
    var lon2 = coord2[0];
    var lat2 = coord2[1];

    var R = 6371000; // earth radius in meters
    var φ1 = toRadians(lat1);
    var φ2 = toRadians(lat2);
    var Δφ = toRadians(lat2-lat1);
    var Δλ = toRadians(lon2-lon1);

    var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
    Math.cos(φ1) * Math.cos(φ2) *
    Math.sin(Δλ/2) * Math.sin(Δλ/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

    return R * c;
    }