I have a set of latitude Longitude points. If I wanted to test if a new point was within x metres of any of the existing points would this be possible?
Would it be best if I use this way?
ForEach(Coordinate coord in Coordinates)
{
var distance = GeoCoordinate.GetDistance(lat,lon);
if(distance <= x)
{
addToQualifyingList(coord);
}
}
and compare the new coordinate with every point in the set and check to see it is within x metres?
Here is a method to calculate the distance between 2 points (lat1, lon1 and lat2, lon2)
public enum DistanceUnit { miles, kilometers, nauticalmiles }
public double GetDistance( double lat1, double lon1 , double lat2 , double lon2, DistanceUnit unit)
{
Func<double, double> deg2rad = deg => (deg * Math.PI / 180.0);
Func<double, double> rad2deg = rad => (rad / Math.PI * 180.0);
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));
dist = Math.Acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (unit == DistanceUnit.kilometers)
{
dist = dist * 1.609344;
}
else if (unit == DistanceUnit.nauticalmiles)
{
dist = dist * 0.8684;
}
return (dist);
}
To determine all Coordinates with distance below 1 kilometer:
List<Coordinate> result = Coordinates.Where(x => GeoCoordinate.GetDistance(lat,lon, x.lan, x.lon, DistanceUnit.kilometers) < 1).ToList();
Latitude and Longitude are both needed to know the position on earth or any other sphere shaped object. These are given in degree from their respective zero line / point.
http://www.movable-type.co.uk/scripts/latlong.html
Has a solution in Java
> var R = 6371e3; // metres
> var φ1 = lat1.toRadians();
> var φ2 = lat2.toRadians();
> var Δφ = (lat2-lat1).toRadians();
> var Δλ = (lon2-lon1).toRadians();
>
> var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
> Math.cos(φ1) * Math.cos(φ2) *
> Math.sin(Δλ/2) * Math.sin(Δλ/2);
> var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
>
> var d = R * c;
Apparently, this is this is one of the best solutions for small distances.
You should be able to just copy and paste it to C#, youll jsut have to change the variable names.
Related
I'm creating a distance calculator in c# using the haversine equation to calculate the distance between longitudes and latitudes but it is giving the wrong output can anyone see why?
the first long and lat values are for a place in Wales (Bangor) and the other is for a place in England (Manchester)
Here is the code:
using System;
public static class Program
{
static double toRadians(double angle)
{
return (angle * Math.PI) / 180;
}
static double CalcDistance(double lon1, double lon2, double lat1, double lat2)
{
lon1 = toRadians(lon1);
lon2 = toRadians(lon2);
lat1 = toRadians(lat1);
lat2 = toRadians(lat2);
//haversine formula
double dlat, dlon;
dlat = lat2 - lat1;
dlon = lon2 - lon1;
double a = Math.Pow(Math.Sin(dlat / 2), 2) *
Math.Cos(lat1) * Math.Cos(lat2) *
Math.Pow(Math.Sin(dlon / 2), 2);
double c = 2 * Math.Asin(Math.Sqrt(a));
// earths radius is KM, use 3956 for miles
double earthRadius = 6371;
return (c * earthRadius);
}
static void Main(String[] args)
{
double lat1, lat2, lon1, lon2;
lon1= 53.222469;
lat1 = -4.129424;
lon2 = 53.244697;
lat2 = -2.13195;
Console.WriteLine(CalcDistance(lon1, lon2, lat1, lat2) + " KM");
}
}
The output given is 0.04301075336978381 KM when the output should be roughly 130KM
The error is a * vs + (the first one in CalcDistance), but here's a direct conversion from https://www.movable-type.co.uk/scripts/latlong.html, for reference (also adding this to the static double toRadians(this double angle) so it works as an extension method):
static double CalcDistance(double lon1, double lon2, double lat1, double lat2)
{
const double R = 6371;
var φ1 = lat1.toRadians();
var φ2 = lat2.toRadians();
var Δφ = (lat2 - lat1).toRadians();
var Δλ = (lon2 - lon1).toRadians();
var a = Math.Sin(Δφ / 2) * Math.Sin(Δφ / 2) +
Math.Cos(φ1) * Math.Cos(φ2) *
Math.Sin(Δλ / 2) * Math.Sin(Δλ / 2);
var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
var d = R * c;
return d;
}
I have two pins on the map with long and latitude and I wish to see the distance between them.
This is what I have so far.
var myPin = new Pin ();
myPin.Label = "pin1";
myPin.Address = "test1";
myPin.Position = new Position(37.797513, -122.402068);
myPin.Label = "pin2";
myPin.Address = "test2";
myPin.Position = new Position(37.7, -122.3);
mymap.Pins.Add(myPin);
So two different pins on my map. How can I see the distance between these two in km? My goal is to make a label with the distance (km) as the text.
(I have a customer renderer base ready incase the only way to solve the distancefunction is via a renderer).
if u have two pins you have their longitude and latitude values , so can calculate the distance between em using below code (taken from geodatasource.com)
private double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
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));
dist = Math.Acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (unit == 'K') {
dist = dist * 1.609344;
} else if (unit == 'N') {
dist = dist * 0.8684;
}
return (dist);
}
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad) {
return (rad / Math.PI * 180.0);
}
so basically you just need one starting reference of lat/long value from where you will take reference for further pin to show this distance as a label
There is one built into the Location class
public static Void DistanceBetween (Double startLatitude, Double startLongitude, Double endLatitude, Double endLongitude, Single[] results)
See this option also using the CoreLocation class
Calculate distance between two positions
i used this code which takes longitude and latitude of two different location and calculates the distance between them
my code is
protected void Button1_Click(object sender, EventArgs e)
{
double lat1= Convert.ToDouble(TextBox1.Text);
double lon1= Convert.ToDouble(TextBox2.Text);
double lat2= Convert.ToDouble(TextBox3.Text);
double lon2= Convert.ToDouble(TextBox4.Text);
var rlat1 = Math.PI * lat1/180;
var rlat2 = Math.PI * lat2/180;
var rlon1 = Math.PI * lon1/180;
var rlon2 = Math.PI * lon2 / 180;
var theta = lon1-lon2;
var rtheta = Math.PI * theta/180;
var dist = Math.Sign(rlat1) * Math.Sign(rlat2) + Math.Cos(rlat1) * Math.Cos(rlat2) * Math.Cos(rtheta);
dist = Math.Acos(dist);
dist = dist * 180/Math.PI;
dist = dist * 60 * 1.1515;
dist = dist * 1.609344 ;
TextBox5.Text = dist.ToString("0.######");
}
but for all the input values the result i am getting is NaN.please help me.
Ok, because I led you up the garden path with my previous answer, I ported this to give you an algorithm that works:
void Main()
{
double lat1=12.916933d,
lon1=77.562658d,
lat2=12.930140d,
lon2=77.587732d;
double dist = GetDistanceFromLatLonInKm(lat1, lon1, lat2, lon2);
// dist == 3.08890370651166 yay!
}
double GetDistanceFromLatLonInKm(double lat1,
double lon1,
double lat2,
double lon2) {
var R = 6371d; // Radius of the earth in km
var dLat = Deg2Rad(lat2 - lat1); // deg2rad below
var dLon = Deg2Rad(lon2 - lon1);
var a =
Math.Sin(dLat / 2d) * Math.Sin(dLat / 2d) +
Math.Cos(Deg2Rad(lat1)) * Math.Cos(Deg2Rad(lat2)) *
Math.Sin(dLon / 2d) * Math.Sin(dLon / 2d);
var c = 2d * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1d - a));
var d = R * c; // Distance in km
return d;
}
double Deg2Rad(double deg) {
return deg * (Math.PI / 180d);
}
Your calculation appears to work correctly when you supply fixed values:
var lat1 = 0d;
var lon1 = 52d;
var lat2 = 0d;
var lon2 = -52d;
which rather implies that these conversions are failing:
double lat1 = Convert.ToDouble(TextBox1.Text);
double lon1 = Convert.ToDouble(TextBox2.Text);
double lat2 = Convert.ToDouble(TextBox3.Text);
double lon2 = Convert.ToDouble(TextBox4.Text);
If you're still having trouble, place a breakpoint on these lines and take a look at the values of TextBox1.Text etc.
For more predictable parsing of floating point numbers, it's best to supply culture information:
Convert.ToDouble("1.2", System.Globalization.CultureInfo.InvariantCulture)
Check if decimal delimiter is valid. It has to be comma or dot, depending on your regional settings.
I am using the following function.
private static Location CoordinateAtADistance(double latOrigin, double lonOrigin, double radius, double angle)
{
double lonDestination;
double R = 6371.0;
double d = radius / R; // d = angular distance covered on earth's surface
double lat1 = ToRadian(latOrigin);
double lon1 = ToRadian(lonOrigin);
double brng = ToRadian(angle);
double latDestination = lat1 + d * Math.Cos(brng);
double dLat = d * Math.Cos(brng);
double dPhi = Math.Log(Math.Tan(latDestination / 2 + Math.PI / 4) / Math.Tan(lat1 / 2 + Math.PI / 4));
double q = (double.IsNaN(dLat / dPhi)) ? dLat / dPhi : Math.Cos(lat1); // E-W line gives dPhi=0
double dLon = d * Math.Sin(brng) / q;
// check for some daft bugger going past the pole
if (Math.Abs(latDestination) > Math.PI / 2)
latDestination = latDestination > 0 ? Math.PI - latDestination : -(Math.PI - latDestination);
lonDestination = (lon1 + dLon +3* Math.PI) % (2 * Math.PI) - Math.PI;
Location nextPoint = new Location();
if (angle == 0)
{
nextPoint.Latitude = ToDegree(latDestination);
nextPoint.Longitude = lonOrigin;
}
if (angle == 90)
{
nextPoint.Latitude = latOrigin;
nextPoint.Longitude = ToDegree(lonDestination);
}
return nextPoint;
}
Here radius is the distance.
Now the problem is when I calculate short distances e.g. a few hundreds kilometers it works perfectly. But for large distances say 11,000 kilometers it gives in correct longitude.
Please not I only move either along latitude or longitude so one of them will not change in any case. While moving for latitude I get correct answer but for longitude values are not even closer.
Please post comments if any thing is unclear.
double latDestination = lat1 + d * Math.Cos(brng);
double dLat = d * Math.Cos(brng);
double dPhi = Math.Log(Math.Tan(latDestination / 2 + Math.PI / 4) / Math.Tan(lat1 / 2 + Math.PI / 4));
double q = (double.IsNaN(dLat / dPhi)) ? dLat / dPhi : Math.Cos(lat1); // E-W line gives dPhi=0
double dLon = d * Math.Sin(brng) / q;
// check for some daft bugger going past the pole
if (Math.Abs(latDestination) > Math.PI / 2)
latDestination = latDestination > 0 ? Math.PI - latDestination : -(Math.PI - latDestination);
lonDestination = (lon1 + dLon + 3 * Math.PI) % (2 * Math.PI) - Math.PI;
A little correction was needed and the above formula works fine.
I am trying to write something that will determine the distance between to sets of lat/lon coordinates.
I am using the following code which I found on this site:
public static double distance (double lat1, double lon1, double lat2, double lon2) {
double lat1 = Convert.ToDouble(latitude);
double lon1 = Convert.ToDouble(longitude);
double lat2 = Convert.ToDouble(destlat);
double lon2 = Convert.ToDouble(destlon);
double theta = toRadians(lon1-lon2);
lat1 = toRadians(lat1);
lon1 = toRadians(lon1);
lat2 = toRadians(lat2);
lon2 = toRadians(lon2);
double dist = sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(theta);
dist = toDegrees(acos(dist)) * 60 * 1.1515 * 1.609344 * 1000;
return dist;
}
My problem is that I am running into the compile error "The name 'toRadians'/'cos'/'sin/'toDegrees' does not exist in the current context..." What am I doing wrong?
You may want to use the following C# class:
public static class GeoCodeCalc
{
public const double EarthRadiusInMiles = 3956.0;
public const double EarthRadiusInKilometers = 6367.0;
public static double ToRadian(double val) { return val * (Math.PI / 180); }
public static double DiffRadian(double val1, double val2) { return ToRadian(val2) - ToRadian(val1); }
public static double CalcDistance(double lat1, double lng1, double lat2, double lng2)
{
return CalcDistance(lat1, lng1, lat2, lng2, GeoCodeCalcMeasurement.Miles);
}
public static double CalcDistance(double lat1, double lng1, double lat2, double lng2, GeoCodeCalcMeasurement m)
{
double radius = GeoCodeCalc.EarthRadiusInMiles;
if (m == GeoCodeCalcMeasurement.Kilometers) { radius = GeoCodeCalc.EarthRadiusInKilometers; }
return radius * 2 * Math.Asin( Math.Min(1, Math.Sqrt( ( Math.Pow(Math.Sin((DiffRadian(lat1, lat2)) / 2.0), 2.0) + Math.Cos(ToRadian(lat1)) * Math.Cos(ToRadian(lat2)) * Math.Pow(Math.Sin((DiffRadian(lng1, lng2)) / 2.0), 2.0) ) ) ) );
}
}
public enum GeoCodeCalcMeasurement : int
{
Miles = 0,
Kilometers = 1
}
Usage:
// Calculate Distance in Miles
GeoCodeCalc.CalcDistance(47.8131545175277, -122.783203125, 42.0982224111897, -87.890625);
// Calculate Distance in Kilometers
GeoCodeCalc.CalcDistance(47.8131545175277, -122.783203125, 42.0982224111897, -87.890625, GeoCodeCalcMeasurement.Kilometers);
Source: Chris Pietschmann - Calculate Distance Between Geocodes in C# and JavaScript
You can write a toRadians function like this:
double ToRadians(double degrees) { return degrees * Math.PI / 180; }
You can write a toDegrees function like this:
double ToDegrees(double radians) { return radians * 180 / Math.PI; }
You should replace sin and cos with Math.Sin and Math.Cos.
This looks like C#.
First you need to define toRadians and toDegrees:
double toRadians(double degrees) {
double sign = Math.Sign(degrees);
while(Math.Abs(degrees) > 360) {
degrees -= sign * 360;
}
return Math.PI * degrees / 180;
}
double toDegrees(double radians) {
double sign = Math.Sign(radians);
while(Math.Abs(radians) > 2 * Math.PI) {
radians -= sign * 2 * Math.PI;
}
return 180 * radians / Math.PI;
}
Then, to use the trigonometric functions you need to use Math.Sin, Math.Cos, etc.
double dist = Math.Sin(lat1) * Math.Sin(lat2)
+ Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(theta);
and
dist = toDegrees(Math.Acos(dist)) * 60 * 1.1515 * 1.609344 * 1000;
Comments:
public static double distance (double lat1, double lon1, double lat2, double lon2) {
double lat1 = Convert.ToDouble(latitude);
double lon1 = Convert.ToDouble(longitude);
double lat2 = Convert.ToDouble(destlat);
double lon2 = Convert.ToDouble(destlon);
What is this? Where are latitude, longitude, destlat and destlon defined? Further, it appears you have lat1, lon1 lat2 and lon2 as parameters to this method so that you can not define locals here with the same name.
double theta = toRadians(lon1-lon2);
lat1 = toRadians(lat1);
lon1 = toRadians(lon1);
lat2 = toRadians(lat2);
lon2 = toRadians(lon2);
This is bad style. If lat1 represents a latitude in degrees it is far better to compute a radians-equivalent value of lat1 like this:
double lat1Radians = toRadians(lat1);
Thus replace the above with:
double theta = toRadians(lon1-lon2);
double lat1Radians = toRadians(lat1);
double lon1Radians = toRadians(lon1);
double lat2Radians = toRadians(lat2);
double lon2Radians = toRadians(lon2);
Lastly:
double dist = sin(lat1) * sin(lat2)
+ cos(lat1) * cos(lat2) * cos(theta);
dist = toDegrees(acos(dist)) * 60 * 1.1515 * 1.609344 * 1000;
This is bad style too. The first formula and the second formula can not both possibly represent the distance that you are trying to calculate. You should assign the result of the first formula to a variable with a more meaningful name. As a worst case, at least do the following:
double temp = Math.Sin(lat1) * Math.Sin(lat2)
+ Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(theta);
double dist = toDegrees(Math.Acos(dist)) * 60 * 1.1515 * 1.609344 * 1000;
return dist;
I know this question is really old, but in case anyone else stumbles across this, use GeoCoordinate from System.Device:
var distanceInMeters = new GeoCoordinate(lat1, lon1)
.GetDistanceTo(new GeoCoordinate(lat2, lon2));
Calculating Distance between Latitude and Longitude points...
double Lat1 = Convert.ToDouble(latitude);
double Long1 = Convert.ToDouble(longitude);
double Lat2 = 30.678;
double Long2 = 45.786;
double circumference = 40000.0; // Earth's circumference at the equator in km
double distance = 0.0;
double latitude1Rad = DegreesToRadians(Lat1);
double latititude2Rad = DegreesToRadians(Lat2);
double longitude1Rad = DegreesToRadians(Long1);
double longitude2Rad = DegreesToRadians(Long2);
double logitudeDiff = Math.Abs(longitude1Rad - longitude2Rad);
if (logitudeDiff > Math.PI)
{
logitudeDiff = 2.0 * Math.PI - logitudeDiff;
}
double angleCalculation =
Math.Acos(
Math.Sin(latititude2Rad) * Math.Sin(latitude1Rad) +
Math.Cos(latititude2Rad) * Math.Cos(latitude1Rad) * Math.Cos(logitudeDiff));
distance = circumference * angleCalculation / (2.0 * Math.PI);
return distance;
You're going to need to adapt this code a bit.
As SLaks, says, you will need to define your own toRadians() method because .NET does not have a native version.
You will also need to change the calls to cos() and sin() to be: Math.Cos() and Math.Sin()