I am trying to calculate the best route to take between all stops w/ GeoCoordinates in C#.
I have some methods which get the next closest location in a list, but I need to be able to sort my original list by:
start -> next stop -> next stop -> next stop -> finish
This is what I'm currently working with:
Models
public class DispatchStopModel
{
public long OrderDispatchID { get; set; }
public long? NextDispatchID { get; set; }
public PhysicalAddress PhysicalAddress { get; set; }
public double Distance { get; set; }
}
Methods
private static double DistanceTo(double lat1, double lon1, double lat2, double lon2, char unit = 'M')
{
double rlat1 = Math.PI * lat1 / 180;
double rlat2 = Math.PI * lat2 / 180;
double theta = lon1 - lon2;
double rtheta = Math.PI * theta / 180;
double dist =
Math.Sin(rlat1) * Math.Sin(rlat2) + Math.Cos(rlat1) *
Math.Cos(rlat2) * Math.Cos(rtheta);
dist = Math.Acos(dist);
dist = dist * 180 / Math.PI;
dist = dist * 60 * 1.1515;
switch (unit)
{
case 'K': //Kilometers -> default
return dist * 1.609344;
case 'N': //Nautical Miles
return dist * 0.8684;
case 'M': //Miles
return dist;
}
return dist;
}
private void FindClosestStop(DispatchStopModel start, ICollection<DispatchStopModel> stops)
{
if(start.PhysicalAddress?.HasGeocode ?? false)
{
foreach(var stop in stops.Where(s => s.OrderDispatchID != start.OrderDispatchID))
{
if(stop.PhysicalAddress?.HasGeocode ?? false)
{
double distanceTo = DistanceTo((double)start.PhysicalAddress.Latitude, (double)start.PhysicalAddress.Longitude, (double)stop.PhysicalAddress.Latitude, (double)stop.PhysicalAddress.Longitude);
if (distanceTo < start.Distance)
{
start.Distance = distanceTo;
start.NextDispatchID = stop.OrderDispatchID;
}
}
}
}
}
Now here is my controller action:
public IActionResult GetDeliveries()
{
var deliveries = deliveryService.GetYourDeliveries();
var Stops = Deliveries.Select(d => new DispatchStopModel
{
OrderDispatchID = d.OrderDispatchID,
NextDispatchID = null,
PhysicalAddress = d.Order.OrderAddress?.PhysicalAddress,
Distance = double.MaxValue
})
.ToArray();
foreach(var stop in Stops)
{
FindClosestStop(stop, Stops);
}
//How can I sort on deliveries using the "NextDispatchID" from the collection I just generated?
}
What I was thinking is that I could setup a new list, and manually insert each delivery where the OrderDispatchID equals the OrderDispatchID of the stop. I feel like this would be inefficient though.
Thoughts on the proper way to do this?
Thanks in advance,