I have been trying to find out what unit the .DistanceTo gives me.
The articles related so far mention geounits, but no further explanation
Using an elapsed time, and 2 locations I am calculating the speed my device is going.
I'm not sure how to get the result from distance=Location1.DistanceTo(Location2); in Km, or any other METRIC unit. I have to use metric for my app.
Any help solving this or guiding me toward the solution would be helpful.
According to the developer documentation the method returns the distance in metres.
Returns the approximate distance in meters between this location and
the given location.
So to get it in kilometres, just divide the result by 1000:
float distanceInMetres = Location1.DistanceTo(Location2);
float distanceInKilometres = distanceInMetres / 1000;
public double CalculationByDistance(GeoPoint StartP, GeoPoint EndP) {
int Radius=6371;//radius of earth in Km
double lat1 = StartP.getLatitudeE6()/1E6;
double lat2 = EndP.getLatitudeE6()/1E6;
double lon1 = StartP.getLongitudeE6()/1E6;
double lon2 = EndP.getLongitudeE6()/1E6;
double dLat = Math.toRadians(lat2-lat1);
double dLon = Math.toRadians(lon2-lon1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2);
double c = 2 * Math.asin(Math.sqrt(a));
double valueResult= Radius*c;
double km=valueResult/1;
DecimalFormat newFormat = new DecimalFormat("####");
kmInDec = Integer.valueOf(newFormat.format(km));
meter=valueResult%1000;
meterInDec= Integer.valueOf(newFormat.format(meter));
Log.i("Radius Value",""+valueResult+" KM "+kmInDec+" Meter "+meterInDec);
return Radius * c;
}
Related
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
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
I'm trying to calculate a new lat long from a point based on a distance in metres from that point.
I've found a few posts on here and elsewhere that helped, but I'm still having a little trouble.
Here's the code I've got so far:
public LatLon CalculateNewCoords(decimal startingLat, decimal startingLon, int distanceEast, int distanceNorth)
{
int r = 6378137;
decimal dLat = Convert.ToDecimal(distanceNorth) / Convert.ToDecimal(r);
decimal pi = Convert.ToDecimal(Math.PI);
double cosInput = Convert.ToDouble(pi * startingLat / Convert.ToDecimal(180));
decimal dLon = Convert.ToDecimal(distanceEast) / Convert.ToDecimal(Convert.ToDouble(r) * Math.Cos(cosInput));
decimal lat0 = startingLat + dLat * (180 * pi);
decimal lon0 = startingLon + dLon * (180 / pi);
LatLon output = new LatLon();
output.Latitude = lat0;
output.Longitude = lon0;
return output;
}
The longitude seems correct, but the latitude is displaying quite significantly out.
I'm using it as follows:
CalculateNewCoords(Convert.ToDecimal(40.743461), Convert.ToDecimal(-74.175847), 0, 1000);
Can someone point out what I'm doing wrong please?
The error is in the first line:
decimal lat0 = startingLat + dLat * (180 * pi);
decimal lon0 = startingLon + dLon * (180 / pi);
this is fore sure not correct, both lines must use the same radians to degrees conversion.
Replace with 180/pi like in line 2.
further think on using double instead if decimal.
I would like to know what's the best way to calculate the current speed with GPS.
I've an external GPS receiver which is connected via USB to my car-notebook. It gives me just the following information:
- Longitude
- Latitude
- Altitude
My try is to get two location-infos with timestamps.
Then I am finding the difference in time (timestamp2 - timestamp1) and calculating the speed (distance/time).
Are there any other possibilites oder maybe any libraries available?
To calculate the distance, you will need the Haversine Formula.
You will find many implementations of it around the web, here is one I use in C#:
private static double ArcInMeters(double lat0, double lon0, double lat1, double lon1)
{
double earthRadius = 6372797.560856; // m
return earthRadius * ArcInRadians(lat0, lon0, lat1, lon1);
}
private static double ArcInRadians(double lat0, double lon0, double lat1, double lon1)
{
double latitudeArc = DegToRad(lat0 - lat1);
double longitudeArc = DegToRad(lon0 - lon1);
double latitudeH = Math.Sin(latitudeArc * 0.5);
latitudeH *= latitudeH;
double lontitudeH = Math.Sin(longitudeArc * 0.5);
lontitudeH *= lontitudeH;
double tmp = Math.Cos(DegToRad(lat0)) * Math.Cos(DegToRad(lat1));
return 2.0 * Math.Asin(Math.Sqrt(latitudeH + tmp * lontitudeH));
}
private static double DegToRad(double x)
{
return x * Math.PI / 180;
}
I have a database with a list of latitude and longitude
-DeviceName
-Latitude
-Longitude
Given my current device's latitude and longitude, I want to get all devices within the database list in distance/proximity of X kilometres.
How do I calculate the proximity of my location vs other locations?
I think you want to have a peep at this amazing presentation. it will tell you how to use (and for bonus points explains!) the haversine formula to calcuate distances on the surface of the earth accounting for curviture and how to avoid some common mistakes in your database queries etc. His dataset is pretty much exactly what yours is - item, longitude and latitude.
If you're after the raw code, this should help you:
private static Double rad2deg(Double rad) {
return (rad / Math.PI * 180.0);
}
private static Double deg2rad(Double deg) {
return (deg * Math.PI / 180.0);
}
private const Double kEarthRadiusKms = 6376.5;
private static Double CalculateDistance(Double latitude1, Double longitude1, Double latitude2, Double longitude2) {
double theta = longitude1 - longitude2;
double dist = Math.Sin(deg2rad(latitude1)) * Math.Sin(deg2rad(latitude2)) + Math.Cos(deg2rad(latitude1)) * Math.Cos(deg2rad(latitude2)) * Math.Cos(deg2rad(theta));
dist = Math.Acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
dist = dist * 1.609344;
return (dist);
}