I am having following JSON array of 6 locations. Is there any way sort these based on longitude and latitude where nearby locations come next in the array?
[
{"id" : 279, "longitude":79.853239,"latitude":6.912283},
{"id" : 284, "longitude":79.865699,"latitude":6.885697},
{"id" : 13, "longitude":79.851187,"latitude":6.912220},
{"id" : 282, "longitude":79.858904,"latitude":6.871041},
{"id" : 281, "longitude":79.853346,"latitude":6.899757},
{"id" : 16, "longitude":79.854786,"latitude":6.894039}
]
Sorting can be started from first item and result should be something like this
[
{"id" : 279, "longitute":79.853239,"latitude":6.912283},
{"id" : 13, "longitute":79.851187,"latitude":6.912220},
{"id" : 281, "longitute":79.853346,"latitude":6.899757},
{"id" : 16, "longitute":79.854786,"latitude":6.894039},
{"id" : 284, "longitute":79.865699,"latitude":6.885697},
{"id" : 282, "longitute":79.858904,"latitude":6.871041}
]
Problem resolved by adding another attribute called distance. Used following function to calculate distance between two points
function calculateDistance(lat1, lon1, lat2, lon2, unit) {
var radlat1 = Math.PI * lat1/180
var radlat2 = Math.PI * lat2/180
var radlon1 = Math.PI * lon1/180
var radlon2 = Math.PI * lon2/180
var theta = lon1-lon2
var radtheta = Math.PI * theta/180
var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
dist = Math.acos(dist)
dist = dist * 180/Math.PI
dist = dist * 60 * 1.1515
if (unit=="K") { dist = dist * 1.609344 }
if (unit=="N") { dist = dist * 0.8684 }
return dist
}
Then calculated distance for each item in the array by using above function. Then sorted array by distance.
for ( i = 0; i < uniqueNodes.length; i++) {
uniqueNodes[i]["distance"] = calculateDistance(uniqueNodes[0]["latitude"],uniqueNodes[0]["longitute"],uniqueNodes[i]["latitude"],uniqueNodes[i]["longitute"],"K");
}
uniqueNodes.sort(function(a, b) {
return a.distance - b.distance;
});
Anyone else looking to do this, if you have the longitude and latitude avaliable, you can just sort linearly on it to get a simple line diagram like below. this will give you a rise/run linear result.
var $array = [
[79.853239, 6.912283, 279],
[79.851187, 6.912220, 13],
[79.853346, 6.899757, 281],
[79.854786, 6.894039, 16],
[79.865699, 6.885697, 284],
[79.858904, 6.87104, 282]
]
function sortLngLat(a, b){
var x = a[0] / a[1];
var y = b[0] / b[1];
}
var sortedArray = $array.sort(sortLngLat);
console.log(sortedArray);
output should be like graph below and you can tweak your values with negatives and positives to get different angles and directions.
---------------
| | / |
| -1/1 | / 1/1 |
| |/ |
|--------------
| /| |
|-1/-1/ | 1/-1 |
| / | |
---------------
If execution speed is relevant, there is no need to calculate the actual distances. This allows for some optimizations. You don't need to multiply by the earth's radius and you to take the square root of the squared differences.
// define local constants for frequently used functions
const asin = Math.asin
const cos = Math.cos
const sin = Math.sin
const PI_180 = Math.PI / 180
function hav(x) {
const s = sin(x / 2)
return s * s
}
function relativeHaversineDistance(lat1, lon1, lat2, lon2) {
const aLatRad = lat1 * PI_180
const bLatRad = lat2 * PI_180
const aLngRad = lon1 * PI_180
const bLngRad = lon2 * PI_180
const ht = hav(bLatRad - aLatRad) + cos(aLatRad) * cos(bLatRad) * hav(bLngRad - aLngRad)
// since we're only interested in relative differences,
// there is no need to multiply by earth radius or to sqrt the squared differences
return asin(ht)
}
const locations = [
{ "id": 279, "longitude": 79.853239, "latitude": 6.912283 },
{ "id": 284, "longitude": 79.865699, "latitude": 6.885697 },
{ "id": 13, "longitude": 79.851187, "latitude": 6.912220 },
{ "id": 282, "longitude": 79.858904, "latitude": 6.871041 },
{ "id": 281, "longitude": 79.853346, "latitude": 6.899757 },
{ "id": 16, "longitude": 79.854786, "latitude": 6.894039 }
]
const distanceTo = {
"id": 279,
"longitude": 79.853239,
"latitude": 6.912283
}
const sorted = locations.sort((a, b) => relativeHaversineDistance(a.latitude, a.longitude, distanceTo.latitude, distanceTo.longitude) - relativeHaversineDistance(b.latitude, b.longitude, distanceTo.latitude, distanceTo.longitude))
console.log(sorted)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With