How to calculate distance between 2 coordinates [duplicate] - c#

This question already has answers here:
Calculating Distance between two Latitude and Longitude GeoCoordinates
(14 answers)
Closed 8 years ago.
I need to find the distance(Km) between 2 points in windows 8.1 apps using c# so i used the function below, but the returned value not correct any help please:
public static double DistanceTo(Double latitude1, Double longitude1, Double latitude2, Double longitude2)
{
var a = latitude1 - latitude2;
var b = longitude1 - longitude2;
return Math.Sqrt(a * a + b * b);
}

You use the wrong formula. That's the reason you don't get the correct result.
The formula you use is the one we use for the calculation of the distance between two points
in the same plane and can be proved using the pythagora's theorem. However when we want to calculate the distance between two point on the surface of a sphere (we assume that the earth is a perfect sphere), we don't use this type.
Here is a link with the correct formula and an implementation in JavaScript.
Below, I have an implementation in C#
At first we have to define a method that would take as a parameter an angle and it will return it's value in radians.
public double ConvertToRadians(double angle)
{
return (Math.PI / 180) * angle;
}
Then we could define our method for the calculation of the distance:
public static double DistanceTo(double latitude1,
double longitude1,
double latitude2,
double longitude2)
{
// The radius of the earth in Km.
// You could also use a better estimation of the radius of the earth
// using decimals digits, but you have to change then the int to double.
int R = 6371;
double f1 = ConvertToRadians(latitude1);
double f2 = ConvertToRadians(latitude2);
double df = ConvertToRadians(latitude1-latitude2);
double dl = ConvertToRadians(longitude1-longitude2);
double a = Math.Sin(dφ/2) * Math.Sin(dφ/2) +
Math.Cos(f1) * Math.Cos(f2) *
Math.Sin(dλ/2) * Math.Sin(dλ/2);
double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1-a));
// Calculate the distance.
double d = R * c;
return d;
}
If you don't want to implement it as above, you could use the GeoCoordinate class, which
Represents a geographical location that is determined by latitude and
longitude coordinates. May also include altitude, accuracy, speed, and
course information.
If you do so, then:
var point1 = new GeoCoordinate(latitude1, longitude1);
var point2 = new GeoCoordinate(latitude2, latitude2);
and then you get the distance between point1 and point2 like below:
point1.GetDistanceTo(point2);

Try something like this:
var coord1 = new GeoCoordinate(lat1, long1);
var coord2 = new GeoCoordinate(lat2, long2);
var distance = coord1.GetDistanceTo(coord2);
Look here. Seems like a duplicate

Related

GPS lap & Segment timer

I've been searching for a while but haven't found exactly what I'm looking for.
I'm working on an app that will go in a race car. It will give the driver the ability to press a button to mark a Start/Finish line. It will also have a button to allow a driver to set segment times.
Keep in mind a track can be an oval which I'm working on first. It could be a road course or it could be an auto cross where the start and finish line aren't the exact same location. They could be with 50 feet of each other or so but the car never crosses where it starts.
I have my gps data coming in and I convert the NMea messages to my classes and I store Lat, Lon, Speed, Course etc. In my research I've ran across this which is interesting. The GPS will be mounted outside the roof for better signal. It generates 10 hits per second. (Garmin Glo)
http://www.drdobbs.com/windows/gps-programming-net/184405690?pgno=1
It's old but it talks about UTM and the Cartesian coordinate system. So using the DecDeg2UTM, I convert Lat & Lon to X & coordinates as well.
I've also been trying to use the Intersect formula I found Here I took the intersect and tried to convert it to C# which I'll post at the end. However, feeding coordinates of an oval track, it doesn't seem to be working. Also, I'm not sure exactly what it's supposed to be doing. But the coordinates it returns when it does somethign like -35.xxx & 98.xxxx which out in an ocean somewhere 1000's of miles from where the track is.
I looking for answers to the following.
I assume I need to take the location recorded when a button is pressed for Start/Finish or Segment and calculate a line perpendicular to the direction the car in able to be able to do some sort of Line Intersection calculation. The Cartesian coordinates seems to calculate the bearing fairly well. But the question here is how do you get the "left and right coordinates". Also, keep in mind, an oval track may be 60 feet wide. But as mentioned an auto cross track may only be 20 ft wide and part of the track may be with 50 ft. Note I'm fine with indicating to set the points, the car needs to be going slow or stopped at the points to get an accurate coordinate. Some tracks they will have to be set while walking the track.
Based on this, should I be trying to use decimal lat lon or would utilizing the Cartesian coordinate system based on UTM be a more accurate method for what I'm trying to do?
Either one is there a .Net library or C based library with source code that has methods for making these calculations?
How can this be accurately handled. (Not that great with Math, links to code samples would help tremendously.)
Next, after I have the lines or whatever is needed for start/finish and segments, as I get GPS sign from the car racing, I need to figure out the most accurate way to tell when a car has crossed those segments. again if I'm lucky I'll get 10 hits per second but it will probably be lower. Then the vehicle speeds could vary significantly depending on the type of track and vehicle. So the GPS hit could be many feet "left or right" of a segment. Also, it could be many feet before or after a segment.
Again, if there is a GIS library out there I can feed coordinates and all this is calculated, that's would work as well as long as it's performant. If not again I'm trying to decide if it's best to break down coordinates to X Y or some geometry formulas for coordinates in decimal format. Mods, I assume there is hard data to support an answer of either way and this isn't responses aren't fully subjective to opinions.
Here is the C# code I came up with from the Script page above. I'm starting to feel UTM and the Cartesian Coordinate system would be better for accuracy and performance. But again I'm open to evidence to the contrary if it exists.
Thanks
P.S. Note GeoCoordinate is from the .Net System.Device.Location assemble. GpsData is just a class I use to convert NMEA messages into Lat, Lon, Course, NumSats, DateTime etc.
The degree Radian methods are extensions as as follows.
public static double DegreeToRadians(this double angle)
{
return Math.PI * angle / 180.0;
}
public static double RadianToDegree(this double angle)
{
return angle * (180.0 / Math.PI);
}
}
public static GeoCoordinate CalculateIntersection(GpsData p1, double brng1, GpsData p2, double brng2)
{
// see http://williams.best.vwh.net/avform.htm#Intersection
// Not sure I need to use Cosine
double _p1LatRadians = p1.Latitude.DegreeToRadians();
double _p1LonToRadians = p1.Longitude.DegreeToRadians();
double _p2LatToRadians = p2.Latitude.DegreeToRadians();
double _p2LonToRadians = p2.Longitude.DegreeToRadians();
double _brng1ToRadians = brng1.DegreeToRadians();
double _brng2ToRadians = brng2.DegreeToRadians();
double _deltaLat = _p2LatToRadians - _p1LatRadians;
double _deltaLon = _p2LonToRadians - _p1LonToRadians;
var _var1 = 2 * Math.Asin(Math.Sqrt(Math.Sin(_deltaLat / 2) * Math.Sin(_deltaLat / 2)
+ Math.Cos(_p1LatRadians) * Math.Cos(_p2LatToRadians) * Math.Sin(_deltaLon / 2) * Math.Sin(_deltaLon / 2)));
if (_var1 == 0) return null;
// initial/final bearings between points
var _finalBrng = Math.Acos((Math.Sin(_p2LatToRadians) - Math.Sin(_p1LatRadians) * Math.Cos(_var1)) / (Math.Sin(_var1) * Math.Cos(_p1LatRadians)));
//if (isNaN(θa)) θa = 0; // protect against rounding
var θb = Math.Acos((Math.Sin(_p1LatRadians) - Math.Sin(_p2LatToRadians) * Math.Cos(_var1)) / (Math.Sin(_var1) * Math.Cos(_p2LatToRadians)));
var θ12 = Math.Sin(_p2LonToRadians - _p1LonToRadians) > 0 ? _finalBrng : 2 * Math.PI - _finalBrng;
var θ21 = Math.Sin(_p2LonToRadians - _p1LonToRadians) > 0 ? 2 * Math.PI - θb : θb;
var α1 = (_brng1ToRadians - θ12 + Math.PI) % (2 * Math.PI) - Math.PI; // angle 2-1-3
var α2 = (θ21 - _brng2ToRadians + Math.PI) % (2 * Math.PI) - Math.PI; // angle 1-2-3
if (Math.Sin(α1) == 0 && Math.Sin(α2) == 0) return null; // infinite intersections
if (Math.Sin(α1) * Math.Sin(α2) < 0) return null; // ambiguous intersection
α1 = Math.Abs(α1);
α2 = Math.Abs(α2);
// ... Ed Williams takes abs of α1/α2, but seems to break calculation?
var α3 = Math.Acos(-Math.Cos(α1) * Math.Cos(α2) + Math.Sin(α1) * Math.Sin(α2) * Math.Cos(_var1));
var δ13 = Math.Atan2(Math.Sin(_var1) * Math.Sin(α1) * Math.Sin(α2), Math.Cos(α2) + Math.Cos(α1) * Math.Cos(α3));
var _finalLatRadians = Math.Asin(Math.Sin(_p1LatRadians) * Math.Cos(δ13) + Math.Cos(_p1LatRadians) * Math.Sin(δ13) * Math.Cos(_brng1ToRadians));
var _lonBearing = Math.Atan2(Math.Sin(_brng1ToRadians) * Math.Sin(δ13) * Math.Cos(_p1LatRadians), Math.Cos(δ13) - Math.Sin(_p1LatRadians) * Math.Sin(_finalLatRadians));
var _finalLon = _p1LonToRadians + _lonBearing;
var _returnLat = _finalLatRadians.RadianToDegree();
var _latToDegree = _finalLon.RadianToDegree();
var _returnLon = ( _latToDegree + 540) % 360 - 180;
return new GeoCoordinate(_returnLat, _returnLon);
//return new LatLon(φ3.toDegrees(), (λ3.toDegrees() + 540) % 360 - 180); // normalise to −180..+180°
}

Calculate point/coordinate from distance and bearing

Maths is not my strong suit and I think I have something mixed up here but I cannot figure out what.
I'm just trying to populate 2 new coordinates given a number of variables and constants.
if I make Origin coordinate 5,5 and Destination coordinate 10,5, I can work out that distance =5 and that the bearing from Origin to Destination is 90 using these two functions:
private static double GetDistance(PointF point1, PointF point2)
{
double a = (double)(point2.X - point1.X);
double b = (double)(point2.Y - point1.Y);
return Math.Sqrt(a * a + b * b);
}
public static double GetBearing(PointF coord1, PointF coord2)
{
double result = 0.0;
result = Math.Atan2(coord2.X - coord1.X, coord2.Y - coord1.Y) * (180 / Math.PI); //- Math.Atan2(coord4.y - coord3.y, coord4.x - coord3.x))
if (result < 0)
{
result = result + 360;
}
return result;
}
What I want to be able to do given an offset Distance of xd=1 and an offset bearing of 180(ie directly opposite direction to the destination) is plot the location 4,5. I'd also like to be able to feed a different offset bearing in of say 90 and plot 5,6.
Here's what I've tried but I get completely nonsensical values.
public static PointF CalculateCoordinate(double Angle, double Distance)
{
PointF coord = new PointF(Convert.ToSingle(Distance * Math.Cos(Angle)), Convert.ToSingle(Distance * Math.Sin(Angle)));
return coord;
}
and CalculateCoordinate(GetBearing(Destination, Origin),1) to reverse the bearing directly 180. I've tried this CalculateCoordinate(90,1) to calculate an offset to the side but that's not working either.
Where have I gone wrong, I'm sure it's something pretty stupid and simple.
There's two mistakes that I can see. First, Atan2 takes the Y value for the first parameter and the X value for the second:
Math.Atan2(coord2.Y - coord1.Y, coord2.X - coord1.X) * (180 / Math.PI);
Secondly, you're converting from radians to degrees in GetBearing, but you're not converting Angle from degrees to radians inside CalculateCoordinate e.g:
Math.Cos(Angle * (Math.PI / 180))

Vehicle GPS Tracking Devices

I am looking to add a feature to a order entry system to show the distance in KM between the order location and assigned delivery van in real time.
The vans have a GPS Tracking system from High Point GPS, comes with an API to query driver location, returns in format of LAT/LONG, and location address if available.
Once I get the location I can use a web service to calculate the distance between the 2 locations, does anyone know what is the best way to get the distance between 2 locations using LAT/LONG for vehicle and address lookup for the delivery location?
You can use Google Maps to get Lat/Long of address
See answer by Thomas Clayson
How can I get latitude, longitude of a location programmatically or using a api
Then you can calculate the distance between the two sets of coordinates by using the Law of Cosines or the Haversine formula
See Law of Cosines
It depends on the other services you are already using. For example, we already use google maps to display the route, so we use their geocoding service to translate from an address to coordinates, as well as their distance service to compute distances.
Create two DbGeography instance for source and destination point (http://msdn.microsoft.com/en-us/library/system.data.spatial.dbgeography.distance(v=vs.110).aspx). Then use distance method of DbGeography for find the distance between two points.
For distance unit refer this post : System.Data.Spatial DbGeography.Distance units?
The simple answer you may find , is a simple formula :
Calculate distance between two points in google maps V3
var rad = function(x) {
return x * Math.PI / 180;
};
var getDistance = function(p1, p2) {
var R = 6378137; // Earth’s mean radius in meter
var dLat = rad(p2.lat() - p1.lat());
var dLong = rad(p2.lng() - p1.lng());
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) *
Math.sin(dLong / 2) * Math.sin(dLong / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d; // returns the distance in meter
};
using google maps api will be the best solution:
https://developers.google.com/maps/documentation/distancematrix/
I've done this but in Java, probably you can port it to c# with no much effort.
This is very accurate for distances shorter than 2000 kilometers, then it can vary a little bit from the real distance. This is due to the earth curvature. But for small distances you can assume it is plain with none or very small impact in the result.
Here is a link I found useful.
And another link, an implementation of Haversine in C#.
Hope it helps.
Best regards, Federico.
public String execute(String plat1, String plon1, String plat2, String plon2) {
String distance;
double lat1, lon1, lat2, lon2;
try{
lat1 = Double.parseDouble(plat1);
lon1 = Double.parseDouble(plon1);
lat2 = Double.parseDouble(plat2);
lon2 = Double.parseDouble(plon2);
} catch (Exception e){
lat1 = 0.0d;
lon1 = 0.0d;
lat2 = 0.0d;
lon2 = 0.0d;
}
//theta and distance
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
//distance
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
dist = dist * 1.609344;
//convert to meters
dist = dist * 1000;
//output in meters
distance = Double.toString(dist);
return distance;
}
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
A little explanation:
(plat1, plon1) is lat and lng of point 1 or origin
(plat2, plon2) is lat and lng of point 2 or destination
the method "execute" is the one you call, it returns a string containing the distance in meters (conversion to other units can be done easily)
two assisting functions are declared as "deg2rad" and "rad2deg".

Calculate angle required to hit coordinate (x,y) from position other than (0,0) with varying elevation

I am attempting to calculate the angle required to fire a projectile in order to hit a specific coordinate.
My projectile is located a random coordinate and my target coordinate at a static coordinate.
I ended up running across the following equation on Wikipedia for calculating the angle required to hit a coordinate at (x,y) from (0,0):
I have made some attempts to understand this and other formula and attempted the following implementation (I am using c# and XNA).
double y = source.Y - target.Y;
double x = Vector2.Distance(source, target);
double v = 1440; //velocity
double g = 25; //gravity
double sqrt = (v*v*v*v) - (g*(g*(x*x) + 2*y*(v*v)));
sqrt = Math.Sqrt(sqrt);
double angleInRadians = Math.Atan(((v*v) + sqrt)/(g*x));
I have also attempted the following, which resulted in an identical angle where the values of v and g remain the same.
double targetX = target.X - source.X;
double targetY = -(target.Y - source.Y);
double r1 = Math.Sqrt((v*v*v*v) - g*(g*(target.X*target.X) + ((2*target.Y)*(v*v))));
double a1 = ((v*v) + r1)/(g*target.X);
angleInRadians = -Math.Atan(a1);
if (targetX < 0)
{
angleInRadians -= 180/180*Math.PI;
}
My conjecture is that even in my (assumed) attempt to zero out the source coordinate, that I am still not performing the calculation correctly for coordinates with a non (0,0) source and different elevations.
Below is an image that depicts my coordinate system. It is the default for XNA.
Thanks to the help in the comments the solution to find this angle ended up requiring that the positions be translated to a (0,0) based system. For anyone looking for the same scenario the final working solution was:
double x = -(source.x - target.x);
double y = (source.y - target.y);
double v = 1440; //m/s
double g = 25; //m/s
double sqrt = (v*v*v*v) - (g*(g*(x*x) + 2*y*(v*v)));
sqrt = Math.Sqrt(sqrt);
angleInRadians = Math.Atan(((v*v) + sqrt)/(g*x));
Then to convert the radians into a vector that works with XNA, perform the following conversion:
Vector2 angleVector = new Vector2(-(float)Math.Cos(angleInRadians), (float)Math.Sin(angleInRadians));
I think the real problem lies in the use of arctan. Because the range is limited to -pi/2..pi/2 results are only in the right half plane.
Use arctan2 to get the proper coordinates:
angleInRadians = Math.Atan2(((v*v) + tmp), (g*x));

In C#, how do I get required number of decimal point values without rounding? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C# Double - ToString() formatting with two decimal places but no rounding
I'm using float numbers and I want to get the number of decimal points without any rounding-off being performed.
For Eg. float x = 12.6789
If I want upto 2 decimal points, then I should get (x = 12.67) and NOT (x = 12.68) which happens when rounding takes place.
Plz suggest which is the best way to do this.
You should be able to use Math.Truncate() for this:
decimal x = 12.6789m;
x = Math.Truncate(x * 100) / 100; //This will output 12.67
You can achieve this by casting:
float x = 12.6789;
float result = ((int)(x * 100.0)) / 100.0;
There is probably a framework call for this, but you could always write one like:
//Scale up, floor, then round down.
//ie: 1.557
// scaled up: 155.7
// floord: 155
// scaled down: 1.55
public float MyTruncate(float f, int precision){
float scale = precision * 10;
return (Math.Floor(f * scale)) / scale;
}

Categories

Resources