What is the fastest way to calculate driving distance in wp8 c#? - c#

I am developing an application which shows driving distances to a certain points from current position of user. There are couple of thousands of coordinate points and the application needs to calculate the distance really fast. Below is the method I'm using.
public async Task<int> findRouteLength(System.Device.Location.GeoCoordinate currentPosition, System.Device.Location.GeoCoordinate businessPosition)
{
List<System.Device.Location.GeoCoordinate> routePositions = new List<System.Device.Location.GeoCoordinate>();
routePositions.Add(currentPosition);
routePositions.Add(businessPosition);
RouteQuery query = new RouteQuery();
query.TravelMode = TravelMode.Driving;
query.Waypoints = routePositions;
Route route = await query.GetRouteAsync();
return route.LengthInMeters;
}
However, this task can only calculate no more than 5-6 distances in one second. Is there any faster way of calculating driving distances in windows phone 8 c# ?

Try this, it should be much faster
public double CalculateDistance(System.Device.Location.GeoCoordinate geo, System.Device.Location.GeoCoordinate geo2)
{
//var R = 6371; // result in km
var R = 6371000; // result in m
var dLat = (geo2.Latitude - geo.Latitude).ToRad();
var dLon = (geo2.Longitude - geo.Longitude).ToRad();
var lat1 = geo.Latitude.ToRad();
var lat2 = geo2.Latitude.ToRad();
var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(lat1) * Math.Cos(lat2);
var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
return R * c;
}
ToRad extension
static class Ext
{
public static double ToRad(this double val)
{
return (Math.PI / 180) * val;
}
}

Related

Calculate Coord from start point, endpoint, and distance

I have two points on a map and I know the distance between them. Now, I need to get a new point between them X meters away from start point. However, i cannot figure out, how to find the new coords.
var nextTrazadoPoint = new Coord {Lat = ...., Lng=...., Alt=...};
var previousTrazadoPoint = new Coord {Lat = ...., Lng=...., Alt...};
var fromCoords = new GeoCoordinate(nextTrazadoPoint.Lat, nextTrazadoPoint.Lng, nextTrazadoPoint.Alt);
var toCoords = new GeoCoordinate(previousTrazadoPoint .Lat, previousTrazadoPoint .Lng, previousTrazadoPoint .Alt);
var distance = fromCoords.GetDistanceTo(toCoords); //Let's say 1000 ¿meters?
Now I want to walk 200 meters from previousTrazadoPoint to nextTrazadoPoint
//Vector from previousTrazadoPoint to nextTrazadoPoint
var vectorDireccion = new Vector(
(double)(nextTrazadoPoint.Latitud - previousTrazadoPoint.Latitud),
(double)(nextTrazadoPoint.Longitud - previousTrazadoPoint.Longitud)
);
//Normalize
vectorDireccion.Normalize();
//meters from previousTrazadoPoint
var distanciaARecorrer = 200;
//New coords
var vectorDestino = distanciaARecorrer * vectorDireccion;
point.Latitud = (decimal)vectorDestino.X + previousTrazadoPoint.Latitud;
point.Longitud = (decimal)vectorDestino.Y + previousTrazadoPoint.Longitud;
However, when i draw the new point on Gmaps, it is not placed between both.
Any ideas?
Thanks to #HansKilian and #cletus (Calculate distance between 2 GPS coordinates), I could find the solution
private const double EARTH_RADIUS = 6378.1;
private static double ConvertToRadians(double angle)
{
return (Math.PI / 180) * angle;
}
private static double ConvertToDegree(double angle)
{
return angle * (180.0 / Math.PI);
}
private static double CalculateBearing(CoordsDto from, CoordsDto to)
{
var from_lat_rad = ConvertToRadians(from.Latitud);
var to_lat_rad = ConvertToRadians(to.Latitud);
var dif_lng_rad = ConvertToRadians(to.Longitud - from.Longitud);
double x = Math.Cos(from_lat_rad) * Math.Sin(to_lat_rad) - Math.Sin(from_lat_rad) * Math.Cos(to_lat_rad) * Math.Cos(dif_lng_rad);
double y = Math.Sin(dif_lng_rad) * Math.Cos(to_lat_rad);
// Math.Atan2 can return negative value, 0 <= output value < 2*PI expected
return (Math.Atan2(y, x) + Math.PI * 2) % (Math.PI * 2);
}
public static CoordsDto GetPointFarAway(CoordsDto from, CoordsDto to, double meterAwayFromStart)
{
var resp = new CoordsDto();
var bearing_rad = CalculateBearing(from, to);
var d = meterAwayFromStart * 0.001; //KM
var input_lat1_rad = ConvertToRadians(from.Latitud);
var input_lon1_rad = ConvertToRadians(from.Longitud);
var newPoint_lat_rad = Math.Asin(
Math.Sin(input_lat1_rad) * Math.Cos(d / EARTH_RADIUS) + Math.Cos(input_lat1_rad) * Math.Sin(d / EARTH_RADIUS) * Math.Cos(bearing_rad)
);
var newPoint_lon_rad = input_lon1_rad + Math.Atan2(
Math.Sin(bearing_rad) * Math.Sin(d / EARTH_RADIUS) * Math.Cos(input_lat1_rad),
Math.Cos(d / EARTH_RADIUS) - Math.Sin(input_lat1_rad) * Math.Sin(newPoint_lat_rad)
);
resp.Latitud = ConvertToDegree(newPoint_lat_rad);
resp.Longitud = ConvertToDegree(newPoint_lon_rad);
return resp;
}
I can't see anything wrong with your code. You haven't really provided enough information that I can take your code and compile it and see what's wrong, so I tried coding it up from scratch using the Vector2 class. I couldn't use Vector since that isn't available in .NET core and my sandbox project is a .NET core project.
This is what I got
var origin = new Vector2(100.0f, 100.0f);
var destination = new Vector2(0.0f, 400.0f);
var direction = destination - origin;
var movement = Vector2.Normalize(direction) * 200.0f;
var movementdestination = origin + movement;
Console.WriteLine($"X: {movementdestination.X}, Y: {movementdestination.Y}");
It prints
X: 36.75444, Y: 289.7367
which - as far as I can tell - is correct. I hope that helps.

A More Efficient Haversine Function

In my previous question, I looked to speed up list selection based on a function result. Now, my bottleneck is the function itself.
It's a basic Haversine function, using the code below:
private static double Haversine(double lat1, double lat2, double lon1, double lon2)
{
const double r = 6371e3; // meters
var dlat = (lat2 - lat1)/2;
var dlon = (lon2 - lon1)/2;
var q = Math.Pow(Math.Sin(dlat), 2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Pow(Math.Sin(dlon), 2);
var c = 2 * Math.Atan2(Math.Sqrt(q), Math.Sqrt(1 - q));
var d = r * c;
return d / 1000;
}
So... why does it need to be so fast? The issue is that I'm calling it a lot. Think north of 16,500,000 times.
Obviously, that's a lot. And in my use case I'm passing it objects that it has to get the location data from and then convert Latitude and Longitude to radians, which increases the time further (only by about 15%). I don't know that there's much I can do about that, but I do know that by passing it purely doubles in radians (as above) it takes ~4.5 seconds - which is more than 75% of the processing time in my implementation. The lines assigning values to q and c seems to take up the most time.
As it's being called a lot, I'm looking to make it a bit faster. I'm open to multithreaded solutions (and am currently working on one myself), but it may be a bit more difficult to implement given the use case in my previous question (linked above).
This was as optimized as I could get the answer (and, to my knowledge, this is the most optimized the answer could possibly get without doing some wizard-level optimization on the formula itself):
private static double Haversine(double lat1, double lat2, double lon1, double lon2)
{
const double r = 6378100; // meters
var sdlat = Math.Sin((lat2 - lat1) / 2);
var sdlon = Math.Sin((lon2 - lon1) / 2);
var q = sdlat * sdlat + Math.Cos(lat1) * Math.Cos(lat2) * sdlon * sdlon;
var d = 2 * r * Math.Asin(Math.Sqrt(q));
return d;
}
On my machine, this formula, when run 16.5 million times, runs at almost exactly 3 seconds, whereas the above version runs at just shy of 5.
However, I maintain that the biggest optimization could be in the system that actually calls this method. 33,000 times on each of 500 Latitude-Longitude pairs? That's a system that is likely in dire need of optimization itself. For starters, you could first calculate the linear-distance-squared of your pairs and only process pairs that are below a certain threshold. Or you could maintain a look-up table to avoid calculating the same pair more than once. Or, depending on the source of that 33,000 number, you can prioritize so that you don't need to call the method nearly that much.
For me this is more accurate
public static class Haversine {
public static double calculate(double lat1, double lon1, double lat2, double lon2) {
var R = 6372.8; // In kilometers
var dLat = toRadians(lat2 - lat1);
var dLon = toRadians(lon2 - lon1);
lat1 = toRadians(lat1);
lat2 = toRadians(lat2);
var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(lat1) * Math.Cos(lat2);
var c = 2 * Math.Asin(Math.Sqrt(a));
return R * c;
}
public static double toRadians(double angle) {
return Math.PI * angle / 180.0;
}
}
void Main() {
Console.WriteLine(String.Format("The distance between coordinates {0},{1} and {2},{3} is: {4}", 36.12, -86.67, 33.94, -118.40, Haversine.calculate(36.12, -86.67, 33.94, -118.40)));
}
// Returns: The distance between coordinates 36.12,-86.67 and 33.94,-118.4 is: 2887.25995060711

How do I find 10 elements by longitude and latitude in 1 km radius using LINQ?

In my case on picture firstPoint0 - as example my first point and center of the circle, relative this point confine screenings by radius 1 km. I need to show just all points in my radius, others points thisPoint not show by linq query.
var flats = context.Flats;
var first = flats.FirstOrDefault(x => x.Lattitude && x.Longitude);
var getAllInRadius = flats.Where(? take points where distance <= 1 km)
Just use the Haversine formula that returns the great-circle distance between two points on a sphere:
// Returns the great circle distance between two flats, as meters
public static double DistanceBetweenFlats(Flat flat1, Flat flat2)
{
const int EarthRadius = 6371;
double latitude = ToRadian(flat2.Latitude - flat1.Latitude);
double longitude = ToRadian(flat2.Longitude - flat1.Longitude);
double tmp = (Math.Sin(latitude / 2) * Math.Sin(latitude / 2)) +
(Math.Cos(ToRadian(flat1.Latitude)) * Math.Cos(ToRadian(flat2.Latitude)) *
Math.Sin(longitude / 2) * Math.Sin(longitude / 2));
double c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(tmp)));
double d = EarthRadius * c;
return d * 1000;
}
...
var centerFlat = ...;
var getAllInRadius = flats.Where(z => DistanceBetweenFlats(centerFlat, z) <= 1000);
Of course all of this assumes you're using LINQ in memory (not LINQ to Entities). If it's not the case, you'll have to use spatial queries.

Accessing azure database in Windows Phone 8.1 app to find shortest distance of a place around

I have a database in azure which consists of lattitude and longitude, and I am trying to get those values and find the values with the shortest distance from the current place. (in the future I intend to plot the place corresponding to the shortest distance on a map) but I am not being able to do so.
The Read() function on MainPage.xaml.cs looks as below:
private async void Read()
{
{ Geolocator geo = new Geolocator();
Geoposition pos = await geo.GetGeopositionAsync();
await App.MobileService.GetTable<Sighting>().ReadAsync().ContinueWith(t =>
{
System.Collections.Generic.IEnumerable<Sighting> items = t.Result;
List<double> distances=new List<double>();
foreach (var record in items)
{
lati = record.Lattitude;
longi = record.Longitude;
double lat2 = lati;
double long2 = longi;
double lat1= pos.Coordinate.Point.Position.Latitude;
double long1=pos.Coordinate.Point.Position.Longitude;
double R = 6371;
double dLat = (lat2 - lat1)*Math.PI/180;
double dLon = (long2 - long1)*Math.PI/180;
lat1 = (lat1) * Math.PI / 180;
lat2 = (lat2) * Math.PI / 180;
double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(lat1) * Math.Cos(lat2);
double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
double d = R * c;
distances.Add(d); }
distances.Sort();
double dd = distances.ElementAt(0);
});
}

Calculating the distance between 2 points in c#

I am trying to sort out a method to calculate the distance between 2 points in c#.
This is the code I have been trying though I fear the answer I get is not correct.
static void Main()
{
//postcode australia 2600 -> 3000
float latA = -31.997976f;
float longA = 115.762877f;
float latB = -31.99212f;
float longB = 115.763228f;
decimal distance = (DistanceBetween(latA, latB, longA, longB));
Console.WriteLine("Distance is" + distance);
Console.ReadLine();
}
static decimal DistanceBetween(float latA, float longA, float latB, float longB)
{
var RadianLatA = Math.PI * latA / 180;
var RadianLatb = Math.PI * latB / 180;
var RadianLongA = Math.PI * longA / 180;
var RadianLongB = Math.PI * longB / 180;
double theDistance = (Math.Sin(RadianLatA)) *
Math.Sin(RadianLatb) +
Math.Cos(RadianLatA) *
Math.Cos(RadianLatb) *
Math.Cos(RadianLongA - RadianLongB);
return Convert.ToDecimal(((Math.Acos(theDistance) * (180.0 / Math.PI)))) * 69.09M * 1.6093M;
}
this was adapted from a response found on this site here
Distance between addresses
Any thoughts on what is going wrong/
Thanks
Ryan
The class I usually use is GeoCoordinate
double latA = -31.997976f;
double longA = 115.762877f;
double latB = -31.99212f;
double longB = 115.763228f;
var locA = new GeoCoordinate(latA, longA);
var locB = new GeoCoordinate(latB, longB);
double distance = locA.GetDistanceTo(locB ); // metres
double lat1 = {};
double lat2 = {};
double lon1 = {};
double lon2 = {};
var R = 6376.5000; //Km
lat1 = lat1.ToRad();
lat2 = lat2.ToRad();
lon1 = lon1.ToRad();
lon2 = lon2.ToRad();
var dLat = lat2 - lat1;
var dLon = lon2 - lon1;
var a = Math.Pow(Math.Sin(dLat / 2), 2) + (Math.Pow(Math.Sin(dLon / 2), 2) * Math.Cos(lat1) * Math.Cos(lat2));
var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
var distance = R * c;
public double ToRad(this double degs) {
return degs * (Math.PI/180.0);
}
Input expects doubles.
This is the haversine formula, it's used to calculate the distances on our globe between two points. This is the distance in a straight line, if you need the distance on a path you will have to find all points on that path and then calculate the distances between each two points and then take the sum of that.
You can use DbGeography for spatial calculation. It has DbGeography.Distance method which is used to calculate the distance between two gps points.
Otherwise, try Ref: Harversine Formula to calculate the distance between two points.
Distance Formula: Given the two points (x1, y1) and (x2, y2), the distance between these points is given by the formula:
use it accordingly

Categories

Resources