I am making a script, I have about 2000 city adresses in my json file with longitutde and latitude.
The script has to calculate with longitude and latitude the distance from the supplied lat/long to each of the entries and
order them in order of nearest.
I need about 10 "nearest" results.
I can calculate the distance, but I can't sort by nearest location.
JSON File :
{ "City A": { "Position": { "Longitude": 9.96233, "Latitude": 49.80404 } }, "City B": { "Position": { "Longitude": 6.11499, "Latitude": 50.76891 } }, "City C": { "Position": { "Longitude": 6.80592, "Latitude": 51.53548 } }, "City D": { "Position": { "Longitude": 9.50523, "Latitude": 51.31991 } }, "City E": { "Position": { "Longitude": 9.66089, "Latitude": 48.70158 } }, "City F": { "Position": { "Longitude": 9.93368, "Latitude": 53.55608 } }, "City G": { "Position": { "Longitude": 11.56122, "Latitude": 48.14496 } }, "City H": { "Position": { "Longitude": 13.34253, "Latitude": 52.5319 } }, "City I": { "Position": { "Longitude": 6.11327, "Latitude": 50.77715 } }, "City J": { "Position": { "Longitude": 13.36671, "Latitude": 52.54344 } }
}jQuery :
var jsonString = '{"City A":{"Position":{"Longitude":9.96233,"Latitude":49.80404}},"City B":{"Position":{"Longitude":6.11499,"Latitude":50.76891}},"City C":{"Position":{"Longitude":6.80592,"Latitude":51.53548}},"City D":{"Position":{"Longitude":9.50523,"Latitude":51.31991}},"City E":{"Position":{"Longitude":9.66089,"Latitude":48.70158}},"City F":{"Position":{"Longitude":9.93368,"Latitude":53.55608}},"City G":{"Position":{"Longitude":11.56122,"Latitude":48.14496}},"City H":{"Position":{"Longitude":13.34253,"Latitude":52.5319}},"City I":{"Position":{"Longitude":6.11327,"Latitude":50.77715}},"City J":{"Position":{"Longitude":13.36671,"Latitude":52.54344}}}';
var myData = JSON.parse(jsonString);
$(document).ready(function () { $.each(myData, function (a, b) { //$("#groups").append("<li>"+b.Position.Longitude+"</li>"); $("#groups").append('<li><h2>' + a + '</h2><p>' + hesapla(9.9608999, 49.7222842, b.Position.Longitude, b.Position.Latitude) + '</p></a></li>'); }); function hesapla(meineLongitude, meineLatitude, long1, lat1) { erdRadius = 6371; meineLongitude = meineLongitude * (Math.PI / 180); meineLatitude = meineLatitude * (Math.PI / 180); long1 = long1 * (Math.PI / 180); lat1 = lat1 * (Math.PI / 180); x0 = meineLongitude * erdRadius * Math.cos(meineLatitude); y0 = meineLatitude * erdRadius; x1 = long1 * erdRadius * Math.cos(lat1); y1 = lat1 * erdRadius; dx = x0 - x1; dy = y0 - y1; d = Math.sqrt((dx * dx) + (dy * dy)); if (d < 1) { return Math.round(d * 1000) +" m" ; } else { return Math.round(d * 10) / 10 +" km" ; } };
}); 2 4 Answers
My solution just creates an array of objects out of the locations and distances, sorts them, then spits them out. I've kept everything as meters instead of kilometers but it will be easy to tweak. Enjoy!
While looping:
distanceObj[i] = { distance: hesapla(9.9608999, 49.7222842, b.Position.Longitude, b.Position.Latitude), location: a
};
++i;Then sort:
distanceObj.sort(function(a,b) { return parseInt(a.distance) - parseInt(b.distance)
});This will explain better:
0Considering that the function you provided to calculate the distance between two coordinates is correct, you can use the following routine to sort the cities according to their distance to a given location:
// user supplied lat/long
var origin = JSON.parse('{"Longitude":9.96233,"Latitude":49.80404}');
// cities to sort
var cities = JSON.parse('{"City A":{"Position":{"Longitude":9.96233,"Latitude":49.80404}},"City B":{"Position":{"Longitude":6.11499,"Latitude":50.76891}},"City C":{"Position":{"Longitude":6.80592,"Latitude":51.53548}},"City D":{"Position":{"Longitude":9.50523,"Latitude":51.31991}},"City E":{"Position":{"Longitude":9.66089,"Latitude":48.70158}},"City F":{"Position":{"Longitude":9.93368,"Latitude":53.55608}},"City G":{"Position":{"Longitude":11.56122,"Latitude":48.14496}},"City H":{"Position":{"Longitude":13.34253,"Latitude":52.5319}},"City I":{"Position":{"Longitude":6.11327,"Latitude":50.77715}},"City J":{"Position":{"Longitude":13.36671,"Latitude":52.54344}}}');
// loop through each city and calculate its distance
var array = [];
for (var name in cities) { var city = cities[name]; array.push({ cityName: name, distance: calculateDistance(origin, city.Position) });
}
// this is the function you provided (slightly modified)
function calculateDistance(p1, p2) { var erdRadius = 6371; p1.Longitude = p1.Longitude * (Math.PI / 180); p1.Latitude = p1.Latitude * (Math.PI / 180); p2.Longitude = p2.Longitude * (Math.PI / 180); p2.Latitude = p2.Latitude * (Math.PI / 180); var x0 = p1.Longitude * erdRadius * Math.cos(p1.Latitude); var y0 = p1.Latitude * erdRadius; var x1 = p2.Longitude * erdRadius * Math.cos(p2.Latitude); var y1 = p2.Latitude * erdRadius; var dx = x0 - x1; var dy = y0 - y1; return Math.sqrt((dx * dx) + (dy * dy));
}
// finaly, sort the cities according to their distance
array.sort(function (a, b) { return a.distance - b.distance;
});Here is a working fiddle.
I would suggest a JSON structure more like this:
[ { "City": "City A", "Position": { "Longitude": 9.96233, "Latitude": 49.80404 } }, { "City": "City B", "Position": { "Longitude": 6.11499, "Latitude": 50.76891 } }
]Where each city is an object all held within an array. This would make it much more accessible and usable.
Then replace your $.each() loop with the following:
$.each(myData, function (a, b)
{ b.Distance = hesapla(9.9608999, 49.7222842, b.Position.Longitude, b.Position.Latitude);
});
myData.sort(function(a, b)
{ var distanceA = parseFloat(a.Distance); var distanceB = parseFloat(b.Distance); if(distanceA > distanceB) { return 1; } else if(distanceA < distanceB) { return -1; } return 0;
});
for(var i = 0, iMax = 10; i < iMax; i++)
{ $("#groups").append('<li><h2>' + myData[i].City + '</h2><p>' + myData[i].Distance + '</p></a></li>');
}This will calculate the distance for each and store it in the city's object, sort by distance, then output the first 10 entries.
2Your object should be a list instead. You can convert it on the fly rather than changing your input.
It's also important to keep your distance calculation as a real number rather than converting it to a string.
function schoneStrecke(d){ if (d < 1) { return Math.round(d * 1000) +" m"; } else { return Math.round(d * 10) / 10 +" km"; }
};And then call it only when creating the output:
$("#groups").append('<li><h2>' + myList[i].name + '</h2><p>' + schoneStrecke(myList[i].distance) + '</p></a></li>');Here's my fiddle:
1