Search code examples
javascriptarraysgeojson

Position compression using relative coordinates in Javascript


Goodafternoon. I have a set of coordinates

[ [ 52.52132, 4.52342 ], [ 52.52144, 4.52352 ], [ 52.52154, 4.52354 ], [ 52.52166, 4.52376 ] ]

How can I transform this that the first position (the first two coordinates) become the base. And all the following positions are relative distances to that base?

So, completely pseudo example:

This

[ [ 52.52132, 4.52342 ], [ 52.52144, 4.52352 ], [ 52.52154, 4.52354 ], [ 52.52166, 4.52376 ] ]

Would then become something like this:

[ [ 52.52132, 4.52342 ], [ 0.4123, 0.1232 ], [ 0.1232, 0.5523 ], [ 0.1233, 0.1232 ] ]

Where the first part [ 52.52132, 4.52342 ] is the starting point. And all other coordinates are relative to the previous one.


Solution

  • Is this what your after..

    I'm not sure how your getting 0.4123, 0.1232, As 52.52144 - 52.52132 = 0.00012

    Also if what your after is a simple LatLng compression / decompression system. I've done a little one here, it's a very simple compressor,.. It does what your after works out the different. But does multiple loops of multiplying the diffs by 1 10 100 1000, etc. And keeps track of what would return the smallest stringified result. In then store the multiplier as the first element.

    eg. Your example would compress to -> 5,52.52132,4.52342,12,10,10,2,12,22

    The 5 would equal a difference mutliplier of 100000, it will use that to work out what to divide the difference by. Adding say zlib to this would most likely then compress even more.

    var g = [ [ 52.52132, 4.52342 ], [ 52.52144, 4.52352 ], [ 52.52154, 4.52354 ], [ 52.52166, 4.52376 ] ],
        n = g.slice(0,1);
    
    function compressLatLng(g) {
      var smallest = null, r, mul;
      if (!g.length) return '';
      for (var l = 1; l < 6; l ++) {
        mul = Math.pow(10, l);
        r = [l,g[0][0],g[0][1]];
        for (var k = 1; k < g.length; k ++) {
          r.push(
            ((g[k][0] - g[k-1][0])*mul).toFixed(5)*1,
            ((g[k][1] - g[k-1][1])*mul).toFixed(5)*1
          );
        }
        var j = r.join(',');
        if (!smallest) smallest = j;
        else if (j.length < smallest.length) smallest = j;
      }  
      return smallest;
    }
    
    function uncompressLatLng(s) {
      var r = s.split(',');
      if (!r.length) return [];
      var mul = Math.pow(10,r[0]);
      var j = [[r[1]*1, r[2]*1]];
      var last = j[0];
      for (var l = 3; l < r.length; l += 2) {
        var t = [
          (last[0] + r[l] / mul).toFixed(5)*1,
          (last[1] + r[l+1] / mul).toFixed(5)*1
        ];
        j.push(t);
        last = t;
      }
      return j;
    }
    
    
    for (var l = 1; l < g.length; l ++) {
      n.push([
        (g[l][0] - g[l-1][0]).toFixed(5)*1,
        (g[l][1] - g[l-1][1]).toFixed(5)*1
      ]);
    }
    
    console.log('O:Original S:Simple C:Compressed U:Uncompressed');
    console.log('O: ' + JSON.stringify(g));
    console.log('S: ' + JSON.stringify(n));
    var compressed = compressLatLng(g);
    console.log('C: ' + compressed);
    console.log('U: ' + JSON.stringify(uncompressLatLng(compressed)));