So I'm trying to create a list of the 15 closest people in an array of varying sizes. The array will almost always be ~100 objects in size, but for the sake of testing, I'm trying to make it work with 10,000 (there may be need for the project to be scaled up to these numbers further down the line).
Currently, the method in place is to loop through the array of people, and calculate their proximity to the user based on both the person in question's and the user's latitude and longitude (the former of which is stored in the array). This is done using the haversine formulae and works well (though it does take ~500 milliseconds).
The problem however is that when run on a mobile device (a Samsung Galaxy S5 for the sake of this example), performance really suffers. The time taken for the S5 to sort through 10,000 records in order of how close they are to a pre-determined latitude and longitude is a staggering 1,500-1,600 milliseconds, an unacceptable delay for an app that will be doing many things either side of this process.
So my question is, am I missing some fundamentally more efficient means of sorting this list? Is there an alternative formulae available that is more efficient? Could I simply calculate the combined difference in Latitude and Longitude in .000001s and sort based on that?
Notes:
The user's location is variable, so proximities cannot be stored
I am aware that I'm asking a mobile CPU to perform 100,000,000 calculations in a short space of time and so this may be unavoidable
The method of sorting is the native JavaScript sort method, below is a simplified version of what I am doing to test these timings:
patientArray.sort(function(a, b)
{
return GetDistanceToPoint(a["Lat"], a["Lng"]) - GetDistanceToPoint(b["Lat"], b["Lng"]);
});
// Function to get the User's distance to a point
function GetDistanceToPoint(Latitude, Longitude)
{
// Check if the User's current Latitude and Longitude are available
if(currentLat && currentLng)
{
// Convert degrees to a radius
function degreeToRadius(degree)
{
return degree * (Math.PI/180)
}
// Variable to store radius of the Earth in Km
var earthRadius = 6371;
// Calculate the distance between the two points
var dLat = degreeToRadius(Latitude-currentLat);
var dLon = degreeToRadius(Longitude-currentLng);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(degreeToRadius(currentLat)) * Math.cos(degreeToRadius(Latitude)) * Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = earthRadius * c;
return d;
}
return "-1";
}