0
votes

I'm looking for the right formula to transform a set of gps coordinats into X/Y pixels to represent dots in a given area.

The ultimate goal is to take a .gpx file for instance (or any array of lat/long pairs), parse it, and generate a png of the track/shape.

I don't care of the world's curbature and all the math that goes into getting the result to be as true to life as possible. Nor do I have to match the positions to a map. I just want the X/Y points to fit inside a given area expressed in pixels.

i have these fiddles:

https://jsfiddle.net/tpwyz2m5/20/

https://jsfiddle.net/bjugo7ff/

The problem is that they are to small, so small in fact that they all point to the same pixel in the given area. You have to multiply them with huge numbers and play around with them in order to get them to fit in the 320x240px area.

In some of the tests i ran i manged to blow up those numbers to get the result i wanted but when i tried it with a new set of coordinates, i got different result, meaning, the dots were to close or to far apart.

What i did in my tests (just to see if the conversion works) was to get the X/Y points from each lat/long. Looped through them to get the min/max values (those were the boundaries of the shape). Then i started multiplying and dividing numbers until i got the shape fit inside the given area.

so, this set of coordinates

var coords = {
    0: {
        lat: '45.88289847',
        lon: '21.52251720'
    },
    1: {
         lat: '45.88570661',
        lon: '21.52431965'
    },
    2: {
        lat: '45.88376483',
        lon: '21.52770996'
    }
};

and this

var coords = {
    0: {
        lat: '45.23621754',
        lon: '20.49499512'
    },
    1: {
        lat: '46.46813299',
        lon: '21.67053223'
    },
    2: {
        lat: '45.59097825',
        lon: '22.74169922'
    }
};

should have very similar result (just like in the fiddles).

here's the entire javascript i used in testing:

var coords = {
    0: {
        lat: '45.88289847',
        lon: '21.52251720'
    },
    1: {
        lat: '45.88570661',
        lon: '21.52431965'
    },
    2: {
        lat: '45.88376483',
        lon: '21.52770996'
    }
};
var w = document.getElementById('box').clientWidth; // 320px
var h = document.getElementById('box').clientHeight; // 240px

for (var key in coords) {
    var lat = coords[key]['lat'];
    var lon = coords[key]['lon'];

    var x = (lon * w) / 360;
    var y = (lat * h) / 180;

    var div = document.getElementById('box');
    var dot = document.createElement("div");
    dot.className = 'dot';
    dot.style.top = y+'px';
    dot.style.left = x+'px';
    div.appendChild(dot);

    console.log(key + ' -> lat:' + lat + '; lon:' + lon + '; x: ' + x + '; y: ' + y);
}

html:

<div id="box"></div>

css:

#box {
    width:320px;
    height:240px;
    border:1px solid #F00;
    position:relative;
}
.dot {
    width:2px;
    height:2px;
    background-color:#00F;
    position:absolute;
}

so the question is, how do i scale or zoom in to fit the dots inside X by Y pixel rectangle.

1
By calculating min and max and scaling accordinglySami Kuhmonen

1 Answers

1
votes

After some thinkering I came up with this. I'm sure it's not the right way to do it, but it gets the job done. If anyone knows of a better (shorter more elegant) way, please share!

fiddle here:

https://jsfiddle.net/g1qtzqhj/

and the javascript as follows:

var div = document.getElementById('box');
var w = div.clientWidth;
var h = div.clientHeight;

var s = 1;
var d = 10;

var min_x = min_y = max_x = max_y = 0;
for (var key in coords) {
    var lat = coords[key]['lat'];
    var lon = coords[key]['lon'];

    var x = (lon * w) / 360;
    coords[key]['x'] = x;

    var y = (lat * h) / 180;
    coords[key]['y'] = y;

    if (x < min_x || min_x == 0)
        min_x = x;
    if (x > max_x || max_x == 0)
        max_x = x;
    if (y < min_y || min_y == 0)
        min_y = y;
    if (y > max_y || max_y == 0)
        max_y = y;
}

var dif_x = max_x - min_x;
var dif_y = max_y - min_y;

var bmax_x = bmax_y = 0;
for (var key in coords) {
    var x = coords[key]['x'] = (coords[key]['x'] - (max_x - dif_x));
    var y = coords[key]['y'] = (coords[key]['y'] - (max_y - dif_y));

    if (x > bmax_x || bmax_x == 0)
        bmax_x = x;
    if (y > bmax_y || bmax_y == 0)
        bmax_y = y;
}

nw = (bmax_x) * s;
nh = (bmax_y) * s;

r_x = w / bmax_x;
r_y = h / bmax_y;

for (var key in coords) {
    var dot = document.createElement('div');
    dot.className = 'dot';
    dot.style.width = d +'px';
    dot.style.height = d +'px';
    dot.style.borderRadius = d +'px';
    dot.style.top = h - (coords[key]['y'] * s * r_y) - (d / 2) + 'px';
    dot.style.left = (coords[key]['x'] * s * r_x) - (d / 2) + 'px';
    div.appendChild(dot);
}

I might have to rethink it (after I get some sleep) because looping through the same object three times does not seem right at all!