Distance between 2 decimal points [duplicate] - c++

How do I calculate the distance between two points specified by latitude and longitude?
For clarification, I'd like the distance in kilometers; the points use the WGS84 system and I'd like to understand the relative accuracies of the approaches available.

This link might be helpful to you, as it details the use of the Haversine formula to calculate the distance.
Excerpt:
This script [in Javascript] calculates great-circle distances between the two points –
that is, the shortest distance over the earth’s surface – using the
‘Haversine’ formula.
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lon2-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Distance in km
return d;
}
function deg2rad(deg) {
return deg * (Math.PI/180)
}

I needed to calculate a lot of distances between the points for my project, so I went ahead and tried to optimize the code, I have found here. On average in different browsers my new implementation runs 2 times faster than the most upvoted answer.
function distance(lat1, lon1, lat2, lon2) {
var p = 0.017453292519943295; // Math.PI / 180
var c = Math.cos;
var a = 0.5 - c((lat2 - lat1) * p)/2 +
c(lat1 * p) * c(lat2 * p) *
(1 - c((lon2 - lon1) * p))/2;
return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}
You can play with my jsPerf and see the results here.
Recently I needed to do the same in python, so here is a python implementation:
from math import cos, asin, sqrt, pi
def distance(lat1, lon1, lat2, lon2):
p = pi/180
a = 0.5 - cos((lat2-lat1)*p)/2 + cos(lat1*p) * cos(lat2*p) * (1-cos((lon2-lon1)*p))/2
return 12742 * asin(sqrt(a)) #2*R*asin...
And for the sake of completeness: Haversine on Wikipedia.

Here is a C# Implementation:
static class DistanceAlgorithm
{
const double PIx = 3.141592653589793;
const double RADIUS = 6378.16;
/// <summary>
/// Convert degrees to Radians
/// </summary>
/// <param name="x">Degrees</param>
/// <returns>The equivalent in radians</returns>
public static double Radians(double x)
{
return x * PIx / 180;
}
/// <summary>
/// Calculate the distance between two places.
/// </summary>
/// <param name="lon1"></param>
/// <param name="lat1"></param>
/// <param name="lon2"></param>
/// <param name="lat2"></param>
/// <returns></returns>
public static double DistanceBetweenPlaces(
double lon1,
double lat1,
double lon2,
double lat2)
{
double dlon = Radians(lon2 - lon1);
double dlat = Radians(lat2 - lat1);
double a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) + Math.Cos(Radians(lat1)) * Math.Cos(Radians(lat2)) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2));
double angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
return angle * RADIUS;
}
}

Here is a java implementation of the Haversine formula.
public final static double AVERAGE_RADIUS_OF_EARTH_KM = 6371;
public int calculateDistanceInKilometer(double userLat, double userLng,
double venueLat, double venueLng) {
double latDistance = Math.toRadians(userLat - venueLat);
double lngDistance = Math.toRadians(userLng - venueLng);
double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
+ Math.cos(Math.toRadians(userLat)) * Math.cos(Math.toRadians(venueLat))
* Math.sin(lngDistance / 2) * Math.sin(lngDistance / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return (int) (Math.round(AVERAGE_RADIUS_OF_EARTH_KM * c));
}
Note that here we are rounding the answer to the nearest km.

Thanks very much for all this. I used the following code in my Objective-C iPhone app:
const double PIx = 3.141592653589793;
const double RADIO = 6371; // Mean radius of Earth in Km
double convertToRadians(double val) {
return val * PIx / 180;
}
-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {
double dlon = convertToRadians(place2.longitude - place1.longitude);
double dlat = convertToRadians(place2.latitude - place1.latitude);
double a = ( pow(sin(dlat / 2), 2) + cos(convertToRadians(place1.latitude))) * cos(convertToRadians(place2.latitude)) * pow(sin(dlon / 2), 2);
double angle = 2 * asin(sqrt(a));
return angle * RADIO;
}
Latitude and Longitude are in decimal. I didn't use min() for the asin() call as the distances that I'm using are so small that they don't require it.
It gave incorrect answers until I passed in the values in Radians - now it's pretty much the same as the values obtained from Apple's Map app :-)
Extra update:
If you are using iOS4 or later then Apple provide some methods to do this so the same functionality would be achieved with:
-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {
MKMapPoint start, finish;
start = MKMapPointForCoordinate(place1);
finish = MKMapPointForCoordinate(place2);
return MKMetersBetweenMapPoints(start, finish) / 1000;
}

This is a simple PHP function that will give a very reasonable approximation (under +/-1% error margin).
<?php
function distance($lat1, $lon1, $lat2, $lon2) {
$pi80 = M_PI / 180;
$lat1 *= $pi80;
$lon1 *= $pi80;
$lat2 *= $pi80;
$lon2 *= $pi80;
$r = 6372.797; // mean radius of Earth in km
$dlat = $lat2 - $lat1;
$dlon = $lon2 - $lon1;
$a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlon / 2) * sin($dlon / 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
$km = $r * $c;
//echo '<br/>'.$km;
return $km;
}
?>
As said before; the earth is NOT a sphere. It is like an old, old baseball that Mark McGwire decided to practice with - it is full of dents and bumps. The simpler calculations (like this) treat it like a sphere.
Different methods may be more or less precise according to where you are on this irregular ovoid AND how far apart your points are (the closer they are the smaller the absolute error margin). The more precise your expectation, the more complex the math.
For more info: wikipedia geographic distance

I post here my working example.
List all points in table having distance between a designated point (we use a random point - lat:45.20327, long:23.7806) less than 50 KM, with latitude & longitude, in MySQL (the table fields are coord_lat and coord_long):
List all having DISTANCE<50, in Kilometres (considered Earth radius 6371 KM):
SELECT denumire, (6371 * acos( cos( radians(45.20327) ) * cos( radians( coord_lat ) ) * cos( radians( 23.7806 ) - radians(coord_long) ) + sin( radians(45.20327) ) * sin( radians(coord_lat) ) )) AS distanta
FROM obiective
WHERE coord_lat<>''
AND coord_long<>''
HAVING distanta<50
ORDER BY distanta desc
The above example was tested in MySQL 5.0.95 and 5.5.16 (Linux).

In the other answers an implementation in r is missing.
Calculating the distance between two point is quite straightforward with the distm function from the geosphere package:
distm(p1, p2, fun = distHaversine)
where:
p1 = longitude/latitude for point(s)
p2 = longitude/latitude for point(s)
# type of distance calculation
fun = distCosine / distHaversine / distVincentySphere / distVincentyEllipsoid
As the earth is not perfectly spherical, the Vincenty formula for ellipsoids is probably the best way to calculate distances. Thus in the geosphere package you use then:
distm(p1, p2, fun = distVincentyEllipsoid)
Off course you don't necessarily have to use geosphere package, you can also calculate the distance in base R with a function:
hav.dist <- function(long1, lat1, long2, lat2) {
R <- 6371
diff.long <- (long2 - long1)
diff.lat <- (lat2 - lat1)
a <- sin(diff.lat/2)^2 + cos(lat1) * cos(lat2) * sin(diff.long/2)^2
b <- 2 * asin(pmin(1, sqrt(a)))
d = R * b
return(d)
}

The haversine is definitely a good formula for probably most cases, other answers already include it so I am not going to take the space. But it is important to note that no matter what formula is used (yes not just one). Because of the huge range of accuracy possible as well as the computation time required. The choice of formula requires a bit more thought than a simple no brainer answer.
This posting from a person at nasa, is the best one I found at discussing the options
http://www.cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
For example, if you are just sorting rows by distance in a 100 miles radius. The flat earth formula will be much faster than the haversine.
HalfPi = 1.5707963;
R = 3956; /* the radius gives you the measurement unit*/
a = HalfPi - latoriginrad;
b = HalfPi - latdestrad;
u = a * a + b * b;
v = - 2 * a * b * cos(longdestrad - longoriginrad);
c = sqrt(abs(u + v));
return R * c;
Notice there is just one cosine and one square root. Vs 9 of them on the Haversine formula.

There could be a simpler solution, and more correct: The perimeter of earth is 40,000Km at the equator, about 37,000 on Greenwich (or any longitude) cycle. Thus:
pythagoras = function (lat1, lon1, lat2, lon2) {
function sqr(x) {return x * x;}
function cosDeg(x) {return Math.cos(x * Math.PI / 180.0);}
var earthCyclePerimeter = 40000000.0 * cosDeg((lat1 + lat2) / 2.0);
var dx = (lon1 - lon2) * earthCyclePerimeter / 360.0;
var dy = 37000000.0 * (lat1 - lat2) / 360.0;
return Math.sqrt(sqr(dx) + sqr(dy));
};
I agree that it should be fine-tuned as, I myself said that it's an ellipsoid, so the radius to be multiplied by the cosine varies. But it's a bit more accurate. Compared with Google Maps and it did reduce the error significantly.

pip install haversine
Python implementation
Origin is the center of the contiguous United States.
from haversine import haversine, Unit
origin = (39.50, 98.35)
paris = (48.8567, 2.3508)
haversine(origin, paris, unit=Unit.MILES)
To get the answer in kilometers simply set unit=Unit.KILOMETERS (that's the default).

There is some errors in the code provided, I've fixed it below.
All the above answers assumes the earth is a sphere. However, a more accurate approximation would be that of an oblate spheroid.
a= 6378.137#equitorial radius in km
b= 6356.752#polar radius in km
def Distance(lat1, lons1, lat2, lons2):
lat1=math.radians(lat1)
lons1=math.radians(lons1)
R1=(((((a**2)*math.cos(lat1))**2)+(((b**2)*math.sin(lat1))**2))/((a*math.cos(lat1))**2+(b*math.sin(lat1))**2))**0.5 #radius of earth at lat1
x1=R1*math.cos(lat1)*math.cos(lons1)
y1=R1*math.cos(lat1)*math.sin(lons1)
z1=R1*math.sin(lat1)
lat2=math.radians(lat2)
lons2=math.radians(lons2)
R2=(((((a**2)*math.cos(lat2))**2)+(((b**2)*math.sin(lat2))**2))/((a*math.cos(lat2))**2+(b*math.sin(lat2))**2))**0.5 #radius of earth at lat2
x2=R2*math.cos(lat2)*math.cos(lons2)
y2=R2*math.cos(lat2)*math.sin(lons2)
z2=R2*math.sin(lat2)
return ((x1-x2)**2+(y1-y2)**2+(z1-z2)**2)**0.5

I don't like adding yet another answer, but the Google maps API v.3 has spherical geometry (and more). After converting your WGS84 to decimal degrees you can do this:
<script src="http://maps.google.com/maps/api/js?sensor=false&libraries=geometry" type="text/javascript"></script>
distance = google.maps.geometry.spherical.computeDistanceBetween(
new google.maps.LatLng(fromLat, fromLng),
new google.maps.LatLng(toLat, toLng));
No word about how accurate Google's calculations are or even what model is used (though it does say "spherical" rather than "geoid". By the way, the "straight line" distance will obviously be different from the distance if one travels on the surface of the earth which is what everyone seems to be presuming.

You can use the build in CLLocationDistance to calculate this:
CLLocation *location1 = [[CLLocation alloc] initWithLatitude:latitude1 longitude:longitude1];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:latitude2 longitude:longitude2];
[self distanceInMetersFromLocation:location1 toLocation:location2]
- (int)distanceInMetersFromLocation:(CLLocation*)location1 toLocation:(CLLocation*)location2 {
CLLocationDistance distanceInMeters = [location1 distanceFromLocation:location2];
return distanceInMeters;
}
In your case if you want kilometers just divide by 1000.

As pointed out, an accurate calculation should take into account that the earth is not a perfect sphere. Here are some comparisons of the various algorithms offered here:
geoDistance(50,5,58,3)
Haversine: 899 km
Maymenn: 833 km
Keerthana: 897 km
google.maps.geometry.spherical.computeDistanceBetween(): 900 km
geoDistance(50,5,-58,-3)
Haversine: 12030 km
Maymenn: 11135 km
Keerthana: 10310 km
google.maps.geometry.spherical.computeDistanceBetween(): 12044 km
geoDistance(.05,.005,.058,.003)
Haversine: 0.9169 km
Maymenn: 0.851723 km
Keerthana: 0.917964 km
google.maps.geometry.spherical.computeDistanceBetween(): 0.917964 km
geoDistance(.05,80,.058,80.3)
Haversine: 33.37 km
Maymenn: 33.34 km
Keerthana: 33.40767 km
google.maps.geometry.spherical.computeDistanceBetween(): 33.40770 km
Over small distances, Keerthana's algorithm does seem to coincide with that of Google Maps. Google Maps does not seem to follow any simple algorithm, suggesting that it may be the most accurate method here.
Anyway, here is a Javascript implementation of Keerthana's algorithm:
function geoDistance(lat1, lng1, lat2, lng2){
const a = 6378.137; // equitorial radius in km
const b = 6356.752; // polar radius in km
var sq = x => (x*x);
var sqr = x => Math.sqrt(x);
var cos = x => Math.cos(x);
var sin = x => Math.sin(x);
var radius = lat => sqr((sq(a*a*cos(lat))+sq(b*b*sin(lat)))/(sq(a*cos(lat))+sq(b*sin(lat))));
lat1 = lat1 * Math.PI / 180;
lng1 = lng1 * Math.PI / 180;
lat2 = lat2 * Math.PI / 180;
lng2 = lng2 * Math.PI / 180;
var R1 = radius(lat1);
var x1 = R1*cos(lat1)*cos(lng1);
var y1 = R1*cos(lat1)*sin(lng1);
var z1 = R1*sin(lat1);
var R2 = radius(lat2);
var x2 = R2*cos(lat2)*cos(lng2);
var y2 = R2*cos(lat2)*sin(lng2);
var z2 = R2*sin(lat2);
return sqr(sq(x1-x2)+sq(y1-y2)+sq(z1-z2));
}

Here is a typescript implementation of the Haversine formula
static getDistanceFromLatLonInKm(lat1: number, lon1: number, lat2: number, lon2: number): number {
var deg2Rad = deg => {
return deg * Math.PI / 180;
}
var r = 6371; // Radius of the earth in km
var dLat = deg2Rad(lat2 - lat1);
var dLon = deg2Rad(lon2 - lon1);
var a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(deg2Rad(lat1)) * Math.cos(deg2Rad(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = r * c; // Distance in km
return d;
}

Here is the SQL Implementation to calculate the distance in km,
SELECT UserId, ( 3959 * acos( cos( radians( your latitude here ) ) * cos( radians(latitude) ) *
cos( radians(longitude) - radians( your longitude here ) ) + sin( radians( your latitude here ) ) *
sin( radians(latitude) ) ) ) AS distance FROM user HAVING
distance < 5 ORDER BY distance LIMIT 0 , 5;
For further details in the implementation by programming langugage, you can just go through the php script given here

This script [in PHP] calculates distances between the two points.
public static function getDistanceOfTwoPoints($source, $dest, $unit='K') {
$lat1 = $source[0];
$lon1 = $source[1];
$lat2 = $dest[0];
$lon2 = $dest[1];
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
$unit = strtoupper($unit);
if ($unit == "K") {
return ($miles * 1.609344);
}
else if ($unit == "M")
{
return ($miles * 1.609344 * 1000);
}
else if ($unit == "N") {
return ($miles * 0.8684);
}
else {
return $miles;
}
}

here is an example in postgres sql (in km, for miles version, replace 1.609344 by 0.8684 version)
CREATE OR REPLACE FUNCTION public.geodistance(alat float, alng float, blat
float, blng float)
RETURNS float AS
$BODY$
DECLARE
v_distance float;
BEGIN
v_distance = asin( sqrt(
sin(radians(blat-alat)/2)^2
+ (
(sin(radians(blng-alng)/2)^2) *
cos(radians(alat)) *
cos(radians(blat))
)
)
) * cast('7926.3352' as float) * cast('1.609344' as float) ;
RETURN v_distance;
END
$BODY$
language plpgsql VOLATILE SECURITY DEFINER;
alter function geodistance(alat float, alng float, blat float, blng float)
owner to postgres;

Java implementation in according Haversine formula
double calculateDistance(double latPoint1, double lngPoint1,
double latPoint2, double lngPoint2) {
if(latPoint1 == latPoint2 && lngPoint1 == lngPoint2) {
return 0d;
}
final double EARTH_RADIUS = 6371.0; //km value;
//converting to radians
latPoint1 = Math.toRadians(latPoint1);
lngPoint1 = Math.toRadians(lngPoint1);
latPoint2 = Math.toRadians(latPoint2);
lngPoint2 = Math.toRadians(lngPoint2);
double distance = Math.pow(Math.sin((latPoint2 - latPoint1) / 2.0), 2)
+ Math.cos(latPoint1) * Math.cos(latPoint2)
* Math.pow(Math.sin((lngPoint2 - lngPoint1) / 2.0), 2);
distance = 2.0 * EARTH_RADIUS * Math.asin(Math.sqrt(distance));
return distance; //km value
}

I made a custom function in R to calculate haversine distance(km) between two spatial points using functions available in R base package.
custom_hav_dist <- function(lat1, lon1, lat2, lon2) {
R <- 6371
Radian_factor <- 0.0174533
lat_1 <- (90-lat1)*Radian_factor
lat_2 <- (90-lat2)*Radian_factor
diff_long <-(lon1-lon2)*Radian_factor
distance_in_km <- 6371*acos((cos(lat_1)*cos(lat_2))+
(sin(lat_1)*sin(lat_2)*cos(diff_long)))
rm(lat1, lon1, lat2, lon2)
return(distance_in_km)
}
Sample output
custom_hav_dist(50.31,19.08,54.14,19.39)
[1] 426.3987
PS: To calculate distances in miles, substitute R in function (6371) with 3958.756 (and for nautical miles, use 3440.065).

To calculate the distance between two points on a sphere you need to do the Great Circle calculation.
There are a number of C/C++ libraries to help with map projection at MapTools if you need to reproject your distances to a flat surface. To do this you will need the projection string of the various coordinate systems.
You may also find MapWindow a useful tool to visualise the points. Also as its open source its a useful guide to how to use the proj.dll library, which appears to be the core open source projection library.

Here is my java implementation for calculation distance via decimal degrees after some search. I used mean radius of world (from wikipedia) in km. İf you want result miles then use world radius in miles.
public static double distanceLatLong2(double lat1, double lng1, double lat2, double lng2)
{
double earthRadius = 6371.0d; // KM: use mile here if you want mile result
double dLat = toRadian(lat2 - lat1);
double dLng = toRadian(lng2 - lng1);
double a = Math.pow(Math.sin(dLat/2), 2) +
Math.cos(toRadian(lat1)) * Math.cos(toRadian(lat2)) *
Math.pow(Math.sin(dLng/2), 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return earthRadius * c; // returns result kilometers
}
public static double toRadian(double degrees)
{
return (degrees * Math.PI) / 180.0d;
}

Here's the accepted answer implementation ported to Java in case anyone needs it.
package com.project529.garage.util;
/**
* Mean radius.
*/
private static double EARTH_RADIUS = 6371;
/**
* Returns the distance between two sets of latitudes and longitudes in meters.
* <p/>
* Based from the following JavaScript SO answer:
* http://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula,
* which is based on https://en.wikipedia.org/wiki/Haversine_formula (error rate: ~0.55%).
*/
public double getDistanceBetween(double lat1, double lon1, double lat2, double lon2) {
double dLat = toRadians(lat2 - lat1);
double dLon = toRadians(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = EARTH_RADIUS * c;
return d;
}
public double toRadians(double degrees) {
return degrees * (Math.PI / 180);
}

For those looking for an Excel formula based on WGS-84 & GRS-80 standards:
=ACOS(COS(RADIANS(90-Lat1))*COS(RADIANS(90-Lat2))+SIN(RADIANS(90-Lat1))*SIN(RADIANS(90-Lat2))*COS(RADIANS(Long1-Long2)))*6371
Source

there is a good example in here to calculate distance with PHP http://www.geodatasource.com/developers/php :
function distance($lat1, $lon1, $lat2, $lon2, $unit) {
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
$unit = strtoupper($unit);
if ($unit == "K") {
return ($miles * 1.609344);
} else if ($unit == "N") {
return ($miles * 0.8684);
} else {
return $miles;
}
}

Here is the implementation VB.NET, this implementation will give you the result in KM or Miles based on an Enum value you pass.
Public Enum DistanceType
Miles
KiloMeters
End Enum
Public Structure Position
Public Latitude As Double
Public Longitude As Double
End Structure
Public Class Haversine
Public Function Distance(Pos1 As Position,
Pos2 As Position,
DistType As DistanceType) As Double
Dim R As Double = If((DistType = DistanceType.Miles), 3960, 6371)
Dim dLat As Double = Me.toRadian(Pos2.Latitude - Pos1.Latitude)
Dim dLon As Double = Me.toRadian(Pos2.Longitude - Pos1.Longitude)
Dim a As Double = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(Me.toRadian(Pos1.Latitude)) * Math.Cos(Me.toRadian(Pos2.Latitude)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2)
Dim c As Double = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a)))
Dim result As Double = R * c
Return result
End Function
Private Function toRadian(val As Double) As Double
Return (Math.PI / 180) * val
End Function
End Class

I condensed the computation down by simplifying the formula.
Here it is in Ruby:
include Math
earth_radius_mi = 3959
radians = lambda { |deg| deg * PI / 180 }
coord_radians = lambda { |c| { :lat => radians[c[:lat]], :lng => radians[c[:lng]] } }
# from/to = { :lat => (latitude_in_degrees), :lng => (longitude_in_degrees) }
def haversine_distance(from, to)
from, to = coord_radians[from], coord_radians[to]
cosines_product = cos(to[:lat]) * cos(from[:lat]) * cos(from[:lng] - to[:lng])
sines_product = sin(to[:lat]) * sin(from[:lat])
return earth_radius_mi * acos(cosines_product + sines_product)
end

function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2,units) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lon2-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
var miles = d / 1.609344;
if ( units == 'km' ) {
return d;
} else {
return miles;
}}
Chuck's solution, valid for miles also.

In Mysql use the following function pass the parameters as using POINT(LONG,LAT)
CREATE FUNCTION `distance`(a POINT, b POINT)
RETURNS double
DETERMINISTIC
BEGIN
RETURN
GLength( LineString(( PointFromWKB(a)), (PointFromWKB(b)))) * 100000; -- To Make the distance in meters
END;

Related

Need help expanding particle system spread / divergence from 2 to 3 dimensions

I need help. I've been struggling with this for a week now and getting nowhere. I am building a 3D particle system mainly for learning and I am currently working on particle spread / divergence. In specific, introducing random direction to the particle direction so as to create something that looks more like a fountain as opposed to a solid stream.
I have been successful in getting this to work in one axis but no matter what I do, I cannot get it to work in 3 dimensions.
Here is what I am doing:
// Compute a random angle between -180 to +180 for velocity angle x, y and z. spreadAmount is a float from 0.0 to 1.0 to control degree of spread.
float velangrndx = spreadAmount * ((((double)(rand() % RAND_MAX) / (RAND_MAX)) - 0.5) * 360.0 * 3.14159265359 / 180.0);
float velangrndy = spreadAmount * ((((double)(rand() % RAND_MAX) / (RAND_MAX)) - 0.5) * 360.0 * 3.14159265359 / 180.0);
float velangrndz = spreadAmount * ((((double)(rand() % RAND_MAX) / (RAND_MAX)) - 0.5) * 360.0 * 3.14159265359 / 180.0);
// Compute Angles
float vsin_anglex_dir = -PF_SIN(velangrndx);
float vcos_anglex_dir = -PF_COS(velangrndx);
float vsin_angley_dir = -PF_SIN(velangrndy);
float vcos_angley_dir = -PF_COS(velangrndy);
float vsin_anglez_dir = -PF_SIN(velangrndz);
float vcos_anglez_dir = -PF_COS(velangrndz);
// Assign initial velocity to velocity x, y, z. vel is a float ranging from 0.0 - 0.1 specified by user. velx, vely, and velz are also floats.
velx = vel; vely = vel; velz = vel;
And finally, we get to the particle spread / divergence function below. If I use only the first X axis (comment out the Y and Z) it works as it should (see images), but if I use the Y and Z axis, it works totally incorrectly. px0, py0, and pz0 are temporary float variables so as to preserve the velocity variables.
// X Divergence
px0 = (velx * vsin_anglex_dir);
py0 = (velx * vcos_anglex_dir);
pz0 = velz;
velx = px0; vely = py0; velz = pz0;
// Y Divergence
py0 = (vely * vsin_angley_dir);
pz0 = (vely * vcos_angley_dir);
px0 = velx;
velx = px0; vely = py0; velz = pz0;
// Z Divergence
pz0 = (velz * vsin_anglez_dir);
px0 = (velz * vcos_anglez_dir);
py0 = vely;
velx = px0; vely = py0; velz = pz0;
The velx, vely, and velz are then used to calculate for particle screen position.
This is what the particle spread looks like at 25%, 75% and 100% for the X axis only (if I comment out the Y and Z code). This works as it should and in theory, if the rest of my code was working correctly, I should get this same result for the Y and Z axis. But I don't.
I could really use some help here. Any suggestions on what I am doing wrong and how to correctly expand the currently working spread function from 2 dimensions to 3?
Thanks,
-Richard
Likely it is because the values of velx, vely and velz are getting overwritten on subsequent calculations. See whether the below works the way you are expecting.
// X Divergence
float velxXD = (velx * vsin_anglex_dir);
float velyXD = (velx * vcos_anglex_dir);
float velzXD = velz;
// Y Divergence
float velxYD = velx;
float velyYD = (vely * vsin_angley_dir);
float velzYD = (vely * vcos_angley_dir);
// Z Divergence
float velxZD = (velz * vcos_anglez_dir);
float velyZD = vely;
float velzZD = (velz * vsin_anglez_dir);
velx=velxXD+velxYD+velxZD;
vely=velyXD+velyYD+velyZD;
velz=velzXD+velzYD+velzZD;

Convert lat, long to x, y on Mollweide

I have tried to follow the instructions here but I get wild results compared to this site.
Here is my code.
#include <cmath>
double solveNR(double latitude, double epsilon) {
if (abs(latitude) == M_PI / 2) {
return latitude;
}
double theta = latitude;
while (true) {
double nextTheta = theta - (2 * theta * std::sin(2 * theta) - M_PI * std::sin(latitude)) / (2 + 2 * std::cos(2 * theta));
if (abs(theta - nextTheta) < epsilon) {
break;
}
theta = nextTheta;
}
return theta;
}
void convertToXY(double radius, double latitude, double longitude, double* x, double* y) {
latitude = latitude * M_PI / 180;
longitude = longitude * M_PI / 180;
double longitudeZero = 0 * M_PI / 180;
double theta = solveNR(latitude, 1);
*x = radius * 2 * sqrt(2) * (longitude - longitudeZero) * std::cos(theta) / M_PI;
*y = radius * sqrt(2) * std::sin(theta);
}
For instance,
180 longitude = 21
90 latitude = 8.1209e+06
assuming a radius of 5742340.81
I found this resource which seems to calculate the right answer. But I cannot parse how it is different.
In your solveNR() function why do you use
double nextTheta = theta - (2 * theta * std::sin(2 * theta) - PI *
std::sin(latitude)) / (2 + 2 * std::cos(2 * theta));
instead
double nextTheta = theta - (2 * theta + std::sin(2 * theta) - PI *
std::sin(latitude)) / (2 + 2 * std::cos(2 * theta));
Seems like you should use "+" instead "*" (after 2 * theta in the numerator), to accord with wiki-instructions.

Audio equalization

I'm developing audio player using FFmpeg and I want to add audio equaliqer to my app. I use FFmpeg to get audio samples and compute FFT, but when I try to apply one of IIR filters, I'm geting very noisy audio signal.
This is my code:
double Q = 1.0;
double omega = 2.0 * PI * 1000.0 / 44100.0;
double sine = sin(omega);
double alpha = sine / ( 2.0 * Q);
double cosine = cos(omega);
double b0 = (1 + cosine)/2;
double b1 = (-1) * (1 + cosine);
double b2 = (1 + cosine)/2;
double a0 = 1 + alpha;
double a1 = (-2) * cosine;
double a2 = 1 - alpha;
for( int n = 2; n < fftSize; n++ )
{
leftChannel2[n].re = ((b0/a0)*leftChannel[n].re + (b1/a0)*leftChannel[n-1].re + (b2/a0)*leftChannel[n-2].re -
(a1/a0)*leftChannel2[n-1].re - (a2/a0)*leftChannel2[n-2].re);
rightChannel2[n].re = ((b0/a0)*rightChannel[n].re + (b1/a0)*rightChannel[n-1].re + (b2/a0)*rightChannel[n-2].re -
(a1/a0)*rightChannel2[n-1].re - (a2/a0)*rightChannel2[n-2].re);
leftChannel2[n].im = leftChannel[n].im;
rightChannel2[n].im = rightChannel[n].im;
}
Can anybody told me what is wrong with this code?
Does this filter perform correctly in Excel or Matlab? At first look, i don't see here syntax or semantic errors. By the way, this filter (difference equation) computes frequency response in time domain. What about the imaginary part of the signal? If it is non-zero, you have to filter it in the same way.

How do I calculate the PDF of a bivariate normal distribution?

I have a set of points and extract a small subset of them for calculating a bivariate normal distribution. Afterwards I check all other points if they fit in this distribution by calculating the PDF for every point and rejecting points with a value below some threshold.
So much about the theory...
The PDF has according to wikipedia the formula:
σ is the standard deviation and μ is the mean, calculated as following:
cv::Scalar mean;
cv::Scalar stdDev;
dataPoints = dataPoints.reshape(3); // convert 3 columns to 3 channels
cv::meanStdDev(dataPoints, mean, stdDev);
dataPoints = dataPoints.reshape(1); // convert back
meanX = mean.val[0];
meanY = mean.val[1];
sigmaX = stdDev.val[0];
sigmaY = stdDev.val[1];
dataPoints is a cv::Mat with 3 columns of floats (x, y, index).
ρ is the correlation coefficient which I calculate like this:
cv::matchTemplate(dataPoints.col(0), dataPoints.col(1), rho, cv::TM_CCOEFF_NORMED);
The last step is calculating the the probability for each point using this:
double p = (1. / (2. * M_PI * sigmaX * sigmaY * sqrt(1. - pow(rho, 2))));
double e = exp((-1. / 2.) * D(x, y, rho));
double ret = p * e;
And D() should be as far as I know the Mahalanobis Distance, but the formula from OpenCV cv::Mahalanobis(x, y, rho) returns another value than when I calculate it myself:
double cX = (x - meanX) / sigmaX;
double cY = (y - meanY) / sigmaY;
double a = (1. / (1. - pow(rho, 2)));
double b = (pow(cX, 2) + pow(cY, 2) - 2. * rho * cX * cY);
double ret = a * b;
So and now my Problem:
As far as I know the integral over the PDF should be 1 and the maximum value of the PDF should be at (meanX, meanY), so when σ would be 0 the PDF at mean should be 1. But with the computations above I can get values over 1. What do I get wrong?

whats best way to start solving by iteration?

I am working on a home project where I need to closely solve an equation by iteration.
M = E - e* sin(E) or another way (E - e*sin(E))/M = 1.
M is previously solved for and e is given in the data message.
So would you plug in a number for E and check to see how close the value ends up to 1, then continue to adjust the plug in value of E untill the expression is within a set value to 1.00000?
Is there an "ideal" method to solving something like this in software?
The rest of my calculation function is shown as
FP64 is defined as double
bool SV_pos_GAL_L1(int chan, FP64* x, FP64* y, FP64* z) //finds SV ECEF position in orbit at ref GAL system time
{
FP64 smaxis = pow(GALChannel[chan].L1galData.sqrrtA, 2); //semi major axis
FP64 nc = sqrt( MU/(pow(smaxis, 3)) ) + GALChannel[chan].L1galData.delta_n; //n corrected
FP64 Tk = GALChannel[chan].L1galData.TOW - GALChannel[chan].L1galData.Toe; //time since ephemeris
FP64 M = GALChannel[chan].L1galData.M0 + nc * Tk; //mean anomaly
FP64 E;
FP64 v = atan( ((sqrt(1-pow(GALChannel[chan].L1galData.e,2)) * sin(E)) / (1-(GALChannel[chan].L1galData.e*cos(E)))) / ((cos(E)-GALChannel[chan].L1galData.e) / (1-(cos(E)*GALChannel[chan].L1galData.e))) );//true anomaly
FP64 Omega = GALChannel[chan].L1galData.Omega0 + (Tk * (GALChannel[chan].L1galData.dot_Omega - GALChannel[chan].L1galData.w)) - ( GALChannel[chan].L1galData.w * GALChannel[chan].L1galData.Toe); //corrected longitude of ascinding node
FP64 ArgLat = v + Omega; //argument of latitude
FP64 Su = (GALChannel[chan].L1galData.Cus * sin(2*ArgLat)) + ( GALChannel[chan].L1galData.Cuc * cos(2*ArgLat)); //argument of latitude correction
FP64 Sr = (GALChannel[chan].L1galData.Crs * sin(2*ArgLat)) + ( GALChannel[chan].L1galData.Crc * cos(2*ArgLat)); //radius correction
FP64 Si = (GALChannel[chan].L1galData.Cis * sin(2*ArgLat)) + ( GALChannel[chan].L1galData.Cic * cos(2*ArgLat)); //inclination correction
FP64 u = ArgLat + Su; //corrected arg latitude
FP64 r = smaxis * (1 - (GALChannel[chan].L1galData.e * cos(E))) + Sr; //corrected radius
FP64 i = GALChannel[chan].L1galData.i0 + Si + (GALChannel[chan].L1galData.dot_i * Tk); //corrected inclination
FP64 x1 = r * cos(u);
FP64 y1 = r * sin(u);
x = (x1 * cos(Omega)) - (y1 * cos(i) * sin(Omega));
y = (x1 * sin(Omega)) - (y1 * cos(i) * cos(Omega));
z = y1 * sin(i);
return true;
}