Get out from smog – part IV
As i mentioned in a previous post. I create a class that will be calculated the distance in kilometers between the measuring stations and a latitudes, longitudes. First we have to calculate distance in kilometers between latidute and longtidute points.
Haversine formula
In this example, I use Haversine formula to calculate distance.
I wrote it in delegate Func which has four parameters and return ‘double’ as a result.
Func<double, double, double, double, double> calculateDistanceToKm = (double _stationLatitudes , double _stationLongtitudes, double _userLatitudes, double _userLongtitudes ) => { var R = 6372.8; // In kilometers var dLat = toRadians(_stationLatitudes - _userLatitudes); var dLon = toRadians(_stationLongtitudes - _userLongtitudes); _userLatitudes = toRadians(_userLatitudes); _stationLatitudes = toRadians(_stationLatitudes); var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(_stationLatitudes) * Math.Cos(_userLatitudes); var c = 2 * Math.Asin(Math.Sqrt(a)); return Math.Round(R * 2 * Math.Asin(Math.Sqrt(a)),3); };
Next I filters my list to receive only stations that are up away max. 100km and added properties which defines the distance from the station.
The whole class looks like this:
public class ReturnNearestStationsIn100Km: IReturnNearestStation { public List<ParseJsonToList> ReturnNearestStation(List<ParseJsonToList> model, double userLatitudes, double userLongitudes) { Func<double, double, double, double, double> calculateDistanceToKm = (double _stationLatitudes, double _stationLongtitudes, double _userLatitudes, double _userLongtitudes) => { var R = 6372.8; // In kilometers var dLat = toRadians(_stationLatitudes - _userLatitudes); var dLon = toRadians(_stationLongtitudes - _userLongtitudes); _userLatitudes = toRadians(_userLatitudes); _stationLatitudes = toRadians(_stationLatitudes); var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(_stationLatitudes) * Math.Cos(_userLatitudes); var c = 2 * Math.Asin(Math.Sqrt(a)); return Math.Round(R * 2 * Math.Asin(Math.Sqrt(a)), 3); }; var filtredModel = model.Where(x => { var distanceInKmFromUserToStation = calculateDistanceToKm(x.LatAndLong.Latitudes, x.LatAndLong.Longitudes, userLatitudes, userLongitudes); x.DistanceBetweenUserAndStation = distanceInKmFromUserToStation; return (distanceInKmFromUserToStation < 100); }).ToList(); return filtredModel; } public double toRadians(double angle) { return Math.PI * angle / 180.0; } }
And here is test for check the distance between the Main Market Square in Krakow and the Wawel Dragon which is ~1012 meters.
Test class:
public class CalculateDistanceBetweenLatiduteAndLongitudeTest { [Fact] public void Distance_between_main_market_square_and_wawel_dragon_should_be_1km_and_12meters() { double _mainMarketSquareCracovLatitude = 50.061858; double _mainMarketSquareCracovlongtitude = 19.936833; double _wawelDragonLatitude = 50.053001; double _wawelDragonLongtitude = 19.933568; List<ParseJsonToList> model = new List<ParseJsonToList>(); LatitudesLongitudes testLatAndLong = new LatitudesLongitudes(); testLatAndLong.Latitudes = _mainMarketSquareCracovLatitude; testLatAndLong.Longitudes = _mainMarketSquareCracovlongtitude; model.Add(new ParseJsonToList() { LatAndLong = testLatAndLong }); ReturnNearestStationsIn100Km calc = new ReturnNearestStationsIn100Km(); var result = calc.ReturnNearestStation(model, _wawelDragonLatitude, _wawelDragonLongtitude); Assert.Equal(1.012d, result.FirstOrDefault().DistanceBetweenUserAndStation); } }
Distance from google maps.
Summary
The next step will be combining all written so far functionality and display the nearest station’s.
Link to the project: HERE.