Calculate distance between 2 lat longs - r

I have 4 columns in my data frame lat1,long1...lat2,long2. I need to calculate distance between these pairs. I am trying to use Distm function.
When I try to use distm (c(mydata2$lst_upd_longitude,mydata2$lst_upd_latitude), c(mydata2$long,mydata2$lat), fun = distHaversine)
R throws up an error "Error in .pointsToMatrix(x) : Wrong length for a vector, should be 2"
For now I am using the below code to calculate distance for every point. But I am sure there should be a better solution. Also this code consumes lot of time.
for( i in 1:nrow(mydata2)){
mydata2$distance[i] <- distm (c(mydata2$lst_upd_longitude[i],mydata2$lst_upd_latitude[i]),
c( mydata2$long[i],mydata2$lat[i]),
fun = distHaversine)}

Try
df <- read.table(sep=",", col.names=c("lat1", "lon1", "lat2", "lon2"), text="
52,4,52,13
39,116,52,13")
library(geosphere)
distHaversine(df[, 2:1], df[, 4:3]) / 1000 # Haversine distance in km

Please try the below Script Code:
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)
}
For more details follow the below link:
Calculate distance between two latitude-longitude points? (Haversine formula)

Related

Always display network nodes in a ring in Vis.js

I tried reading the documentation but couldn't find what I was looking for. This is what I want, how can I do it? Thank you.
You can use the initRedraw event to calculate and to set the node coordinates for a circular layout:
var radius = 150
network.on('initRedraw', function () {
var ids = data.nodes.getIds()
var d = 2 * Math.PI / ids.length // Angular pitch
ids.forEach(function(id, i) {
var x = radius * Math.cos(d * i)
var y = radius * Math.sin(d * i)
network.moveNode(id, x, y)
})
})
https://jsfiddle.net/L6s6hjwz/

Calculate min distance between a "line" and one "point"

I have a "linestring" (with init and end points) and a single "point" (two coordinates).
And I have implemented the following ActionSctipt code to use "haversine formula" to calculate the distance between two points (each point has x & y coordinates); this function can return the "distance" in "kms", "meters", "feets" or "miles":
private function distanceBetweenCoordinates(lat1:Number, lon1:Number, lat2:Number, lon2:Number, units:String = "miles"):Number {
var R:int = RADIUS_OF_EARTH_IN_MILES;
if (units == "km") {
R = RADIUS_OF_EARTH_IN_KM;
}
if (units == "meters") {
R = RADIUS_OF_EARTH_IN_M;
}
if (units == "feet") {
R = RADIUS_OF_EARTH_IN_FEET;
}
var dLat:Number = (lat2 - lat1) * Math.PI / 180;
var dLon:Number = (lon2 - lon1) * Math.PI / 180;
var lat1inRadians:Number = lat1 * Math.PI / 180;
var lat2inRadians:Number = lat2 * Math.PI / 180;
var a:Number = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1inRadians) * Math.cos(lat2inRadians);
var c:Number = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d:Number = R * c;
return d;
}
This code is functioning well. But I need to improving this code to allow calculate the minimum distance between a "single point" and one "linestring" (with 2 points).
How can I do?
I thought this solution:
* Divide the "linesting" for each point (Init and end)... and for each of these calculate the distance to the "single point"... and after I getting both "distances" return the minimum distance.
This solution is not the better, this is explained in the following image:
"d1" and "d2" distances are invalid... because only "d0" is the valid distance.
Please! help me!!! How can I improve the haversine formula to calculate the distance between a line and a single point in kilometres?
Thanks!!!!
In your case d0 distance is a height of triangle. It's Hb=2*A/b where A- Area & b-length of the base side (your linestring).
If given 3 points you can calculate the the distances between them (sides a, b, c of triangle). It will allow you to calculate triangle Area: A=sqrt(p*(p-a)*(p-b)*(p-c)) where p is half perimeter: p=(a+b+c)/2. So, now u have all variables u need to calculate the distance Hb (your "d0").

Optimize the parameterization algorithm of a cubic bezier curve

Except using look-up tables, is there another way to optimize the parameterization algorithm of a cubic Bézier curve like this? (5000 steps for a good parameterization is simply too much for a slower PC, as I need to call this function many times in 1 second):
function parameterizeCurve(path, partArc, initialT)
{
// curve length is already known and globally defined
// brute force
var STEPS = 5000; // > precision
var t = 1 / STEPS;
var aX=0;
var aY=0;
var bX=path[0], bY=path[1];
var dX=0, dY=0;
var dS = 0;
var sumArc = 0;
var arrT = new Array(Math.round(partArc));
var z = 1;
arrT[0] = -1;
var oldpartArc = partArc;
partArc = partArc - initialT;
var j = 0;
for (var i=0; i<STEPS; j = j + t) {
aX = bezierPoint(j, path[0], path[2], path[4], path[6]);
aY = bezierPoint(j, path[1], path[3], path[5], path[7]);
dX = aX - bX;
dY = aY - bY;
// deltaS. Pitagora
dS = Math.sqrt((dX * dX) + (dY * dY));
sumArc = sumArc + dS;
if (sumArc >= partArc) {
arrT[z] = j; // save current t
z++;
sumArc = 0;
partArc = oldpartArc;
}
bX = aX;
bY = aY;
i++;
}
return arrT;
}
function bezierPoint(t, o1, c1, c2, e1) {
var C1 = (e1 - (3.0 * c2) + (3.0 * c1) - o1);
var C2 = ((3.0 * c2) - (6.0 * c1) + (3.0 * o1));
var C3 = ((3.0 * c1) - (3.0 * o1));
var C4 = (o1);
return ((C1*t*t*t) + (C2*t*t) + (C3*t) + C4)
}
If I've guessed correctly, you're trying to come up with a cubic Bezier curve parameterization that moves at a constant speed along the curve.
So, why do you need 5000 steps? The minimum one can move along a curve is one pixel. A Bezier stays within the convex hull of its four control points, so the length of the curve will be less than that of the polyline P0 -> P1 -> P2 -> P3. So find that length in pixels, and use it (instead of 5000).
Let me know if that speeds things up enough.

Get direction (compass) with two longitude/latitude points

I'm working on a "compass" for a mobile-device. I have the following points:
point 1 (current location): Latitude = 47.2246, Longitude = 8.8257
point 2 (target location): Latitude = 50.9246, Longitude = 10.2257
Also I have the following information (from my android-phone):
The compass-direction in degree, which bears to the north.
For example, when I direct my phone to north, I get 0°
How can I create a "compass-like" arrow which shows me the direction to the point?
Is there a mathematic-problem for this?
EDIT: Okay I found a solution, it looks like this:
/**
* Params: lat1, long1 => Latitude and Longitude of current point
* lat2, long2 => Latitude and Longitude of target point
*
* headX => x-Value of built-in phone-compass
*
* Returns the degree of a direction from current point to target point
*
*/
function getDegrees(lat1, long1, lat2, long2, headX) {
var dLat = toRad(lat2-lat1);
var dLon = toRad(lon2-lon1);
lat1 = toRad(lat1);
lat2 = toRad(lat2);
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) -
Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
var brng = toDeg(Math.atan2(y, x));
// fix negative degrees
if(brng<0) {
brng=360-Math.abs(brng);
}
return brng - headX;
}
O forgot to say I found the answer eventually. The application is to determine compass direction of a transit vehicle and its destination. Essentially, fancy math for acquiring curvature of Earth, finding an angle/compass reading, and then matching that angle with a generic compass value. You could of course just keep the compassReading and apply that as an amount of rotation for your image. Please note this is an averaged determination of the vehicle direction to the end point (bus station) meaning it can't know what the road is doing (so this probably best applies to airplanes or roller derby).
//example obj data containing lat and lng points
//stop location - the radii end point
endpoint.lat = 44.9631;
endpoint.lng = -93.2492;
//bus location from the southeast - the circle center
startpoint.lat = 44.95517;
startpoint.lng = -93.2427;
function vehicleBearing(endpoint, startpoint) {
endpoint.lat = x1;
endpoint.lng = y1;
startpoint.lat = x2;
startpoint.lng = y2;
var radians = getAtan2((y1 - y2), (x1 - x2));
function getAtan2(y, x) {
return Math.atan2(y, x);
};
var compassReading = radians * (180 / Math.PI);
var coordNames = ["N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"];
var coordIndex = Math.round(compassReading / 45);
if (coordIndex < 0) {
coordIndex = coordIndex + 8
};
return coordNames[coordIndex]; // returns the coordinate value
}
ie:
vehicleBearing(mybus, busstation)
might return "NW" means its travelling northwesterly
I found some useful gps coordinates formula in math here.
For this case, here my solution
private double getDirection(double lat1, double lng1, double lat2, double lng2) {
double PI = Math.PI;
double dTeta = Math.log(Math.tan((lat2/2)+(PI/4))/Math.tan((lat1/2)+(PI/4)));
double dLon = Math.abs(lng1-lng2);
double teta = Math.atan2(dLon,dTeta);
double direction = Math.round(Math.toDegrees(teta));
return direction; //direction in degree
}
I couldn't understand your solution well, calculating the slope worked for me.
To modify on efwjames's and your answer. This should do -
import math
def getDegrees(lat1, lon1, lat2, lon2,head):
dLat = math.radians(lat2-lat1)
dLon = math.radians(lon2-lon1)
bearing = math.degrees(math.atan2(dLon, dLat))
return head-bearing
You'd need to calculate an Euclidean vector between your start point and end point, then calculate its angle (let's say relative to positive X) which would be the angle you want to rotate your arrow by.

How can I generate a set of points evenly distributed along the perimeter of an ellipse?

If I want to generate a bunch of points distributed uniformly around a circle, I can do this (python):
r = 5 #radius
n = 20 #points to generate
circlePoints = [
(r * math.cos(theta), r * math.sin(theta))
for theta in (math.pi*2 * i/n for i in range(n))
]
However, the same logic doesn't generate uniform points on an ellipse: points on the "ends" are more closely spaced than points on the "sides".
r1 = 5
r2 = 10
n = 20 #points to generate
ellipsePoints = [
(r1 * math.cos(theta), r2 * math.sin(theta))
for theta in (math.pi*2 * i/n for i in range(n))
]
Is there an easy way to generate equally spaced points around an ellipse?
This is an old thread, but since I am seeking the same task of creating evenly spaced points along and ellipse and was not able to find an implementation, I offer this Java code that implements the pseudo code of Howard:
package com.math;
public class CalculatePoints {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
*
dp(t) = sqrt( (r1*sin(t))^2 + (r2*cos(t))^2)
circ = sum(dp(t), t=0..2*Pi step 0.0001)
n = 20
nextPoint = 0
run = 0.0
for t=0..2*Pi step 0.0001
if n*run/circ >= nextPoint then
set point (r1*cos(t), r2*sin(t))
nextPoint = nextPoint + 1
next
run = run + dp(t)
next
*/
double r1 = 20.0;
double r2 = 10.0;
double theta = 0.0;
double twoPi = Math.PI*2.0;
double deltaTheta = 0.0001;
double numIntegrals = Math.round(twoPi/deltaTheta);
double circ=0.0;
double dpt=0.0;
/* integrate over the elipse to get the circumference */
for( int i=0; i < numIntegrals; i++ ) {
theta += i*deltaTheta;
dpt = computeDpt( r1, r2, theta);
circ += dpt;
}
System.out.println( "circumference = " + circ );
int n=20;
int nextPoint = 0;
double run = 0.0;
theta = 0.0;
for( int i=0; i < numIntegrals; i++ ) {
theta += deltaTheta;
double subIntegral = n*run/circ;
if( (int) subIntegral >= nextPoint ) {
double x = r1 * Math.cos(theta);
double y = r2 * Math.sin(theta);
System.out.println( "x=" + Math.round(x) + ", y=" + Math.round(y));
nextPoint++;
}
run += computeDpt(r1, r2, theta);
}
}
static double computeDpt( double r1, double r2, double theta ) {
double dp=0.0;
double dpt_sin = Math.pow(r1*Math.sin(theta), 2.0);
double dpt_cos = Math.pow( r2*Math.cos(theta), 2.0);
dp = Math.sqrt(dpt_sin + dpt_cos);
return dp;
}
}
(UPDATED: to reflect new packaging).
An efficient solution of this problem for Python can be found in the numeric branch FlyingCircus-Numeric, derivated from the FlyingCircus Python package.
Disclaimer: I am the main author of them.
Briefly, the (simplified) code looks (where a is the minor axis, and b is the major axis):
import numpy as np
import scipy as sp
import scipy.optimize
def angles_in_ellipse(
num,
a,
b):
assert(num > 0)
assert(a < b)
angles = 2 * np.pi * np.arange(num) / num
if a != b:
e2 = (1.0 - a ** 2.0 / b ** 2.0)
tot_size = sp.special.ellipeinc(2.0 * np.pi, e2)
arc_size = tot_size / num
arcs = np.arange(num) * arc_size
res = sp.optimize.root(
lambda x: (sp.special.ellipeinc(x, e2) - arcs), angles)
angles = res.x
return angles
It makes use of scipy.special.ellipeinc() which provides the numerical integral along the perimeter of the ellipse, and scipy.optimize.root()
for solving the equal-arcs length equation for the angles.
To test that it is actually working:
a = 10
b = 20
n = 16
phi = angles_in_ellipse(n, a, b)
print(np.round(np.rad2deg(phi), 2))
# [ 0. 17.55 36.47 59.13 90. 120.87 143.53 162.45 180. 197.55
# 216.47 239.13 270. 300.87 323.53 342.45]
e = (1.0 - a ** 2.0 / b ** 2.0) ** 0.5
arcs = sp.special.ellipeinc(phi, e)
print(np.round(np.diff(arcs), 4))
# [0.3022 0.2982 0.2855 0.2455 0.2455 0.2855 0.2982 0.3022 0.3022 0.2982
# 0.2855 0.2455 0.2455 0.2855 0.2982]
# plotting
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.gca()
ax.axes.set_aspect('equal')
ax.scatter(b * np.sin(phi), a * np.cos(phi))
plt.show()
You have to calculate the perimeter, then divide it into equal length arcs. The length of an arc of an ellipse is an elliptic integral and cannot be written in closed form so you need numerical computation.
The article on ellipses on wolfram gives you the formula needed to do this, but this is going to be ugly.
A possible (numerical) calculation can look as follows:
dp(t) = sqrt( (r1*sin(t))^2 + (r2*cos(t))^2)
circ = sum(dp(t), t=0..2*Pi step 0.0001)
n = 20
nextPoint = 0
run = 0.0
for t=0..2*Pi step 0.0001
if n*run/circ >= nextPoint then
set point (r1*cos(t), r2*sin(t))
nextPoint = nextPoint + 1
next
run = run + dp(t)
next
This is a simple numerical integration scheme. If you need better accuracy you might also use any other integration method.
I'm sure this thread is long dead by now, but I just came across this issue and this was the closest that came to a solution.
I started with Dave's answer here, but I noticed that it wasn't really answering the poster's question. It wasn't dividing the ellipse equally by arc lengths, but by angle.
Anyway, I made some adjustments to his (awesome) work to get the ellipse to divide equally by arc length instead (written in C# this time). If you look at the code, you'll see some of the same stuff -
void main()
{
List<Point> pointsInEllipse = new List<Point>();
// Distance in radians between angles measured on the ellipse
double deltaAngle = 0.001;
double circumference = GetLengthOfEllipse(deltaAngle);
double arcLength = 0.1;
double angle = 0;
// Loop until we get all the points out of the ellipse
for (int numPoints = 0; numPoints < circumference / arcLength; numPoints++)
{
angle = GetAngleForArcLengthRecursively(0, arcLength, angle, deltaAngle);
double x = r1 * Math.Cos(angle);
double y = r2 * Math.Sin(angle);
pointsInEllipse.Add(new Point(x, y));
}
}
private double GetLengthOfEllipse()
{
// Distance in radians between angles
double deltaAngle = 0.001;
double numIntegrals = Math.Round(Math.PI * 2.0 / deltaAngle);
double radiusX = (rectangleRight - rectangleLeft) / 2;
double radiusY = (rectangleBottom - rectangleTop) / 2;
// integrate over the elipse to get the circumference
for (int i = 0; i < numIntegrals; i++)
{
length += ComputeArcOverAngle(radiusX, radiusY, i * deltaAngle, deltaAngle);
}
return length;
}
private double GetAngleForArcLengthRecursively(double currentArcPos, double goalArcPos, double angle, double angleSeg)
{
// Calculate arc length at new angle
double nextSegLength = ComputeArcOverAngle(majorRadius, minorRadius, angle + angleSeg, angleSeg);
// If we've overshot, reduce the delta angle and try again
if (currentArcPos + nextSegLength > goalArcPos) {
return GetAngleForArcLengthRecursively(currentArcPos, goalArcPos, angle, angleSeg / 2);
// We're below the our goal value but not in range (
} else if (currentArcPos + nextSegLength < goalArcPos - ((goalArcPos - currentArcPos) * ARC_ACCURACY)) {
return GetAngleForArcLengthRecursively(currentArcPos + nextSegLength, goalArcPos, angle + angleSeg, angleSeg);
// current arc length is in range (within error), so return the angle
} else
return angle;
}
private double ComputeArcOverAngle(double r1, double r2, double angle, double angleSeg)
{
double distance = 0.0;
double dpt_sin = Math.Pow(r1 * Math.Sin(angle), 2.0);
double dpt_cos = Math.Pow(r2 * Math.Cos(angle), 2.0);
distance = Math.Sqrt(dpt_sin + dpt_cos);
// Scale the value of distance
return distance * angleSeg;
}
From my answer in BSE here .
I add it in stackoverflow as it is a different approach which does not rely on a fixed iteration steps but rely on a convergence of the distances between the points, to the mean distance.
So the calculation is shorter as it depends only on the wanted vertices amount and on the precision to reach (about 6 iterations for less than 0.01%).
The principle is :
0/ First step : calculate the points normally using a * cos(t) and b * sin(t)
1/ Calculate the lengths between vertices
2/ Adjust the angles variations depending on the gap between each distance to the mean distance
3/ Reposition the points
4/ Exit when the wanted precision is reached or return to 1/
import bpy, bmesh
from math import radians, sqrt, cos, sin
rad90 = radians( 90.0 )
rad180 = radians( 180.0 )
def createVertex( bm, x, y ): #uses bmesh to create a vertex
return bm.verts.new( [x, y, 0] )
def listSum( list, index ): #helper to sum on a list
sum = 0
for i in list:
sum = sum + i[index]
return sum
def calcLength( points ): #calculate the lenghts for consecutives points
prevPoint = points[0]
for point in points :
dx = point[0] - prevPoint[0]
dy = point[1] - prevPoint[1]
dist = sqrt( dx * dx + dy *dy )
point[3] = dist
prevPoint = point
def calcPos( points, a, b ): #calculate the positions following the angles
angle = 0
for i in range( 1, len(points) - 1 ):
point = points[i]
angle += point[2]
point[0] = a * cos( angle )
point[1] = b * sin( angle )
def adjust( points ): #adjust the angle by comparing each length to the mean length
totalLength = listSum( points, 3 )
averageLength = totalLength / (len(points) - 1)
maxRatio = 0
for i in range( 1, len(points) ):
point = points[i]
ratio = (averageLength - point[3]) / averageLength
point[2] = (1.0 + ratio) * point[2]
absRatio = abs( ratio )
if absRatio > maxRatio:
maxRatio = absRatio
return maxRatio
def ellipse( bm, a, b, steps, limit ):
delta = rad90 / steps
angle = 0.0
points = [] #will be a list of [ [x, y, angle, length], ...]
for step in range( steps + 1 ) :
x = a * cos( angle )
y = b * sin( angle )
points.append( [x, y, delta, 0.0] )
angle += delta
print( 'start' )
doContinue = True
while doContinue:
calcLength( points )
maxRatio = adjust( points )
calcPos( points, a, b )
doContinue = maxRatio > limit
print( maxRatio )
verts = []
for point in points:
verts.append( createVertex( bm, point[0], point[1] ) )
for i in range( 1, len(verts) ):
bm.edges.new( [verts[i - 1], verts[i]] )
A = 4
B = 6
bm = bmesh.new()
ellipse( bm, A, B, 32, 0.00001 )
mesh = bpy.context.object.data
bm.to_mesh(mesh)
mesh.update()
Do take into consideration the formula for ellipse perimeter as under if the ellipse is squashed. (If the minor axis is three times as small as the major axis)
tot_size = np.pi*(3*(a+b) -np.sqrt((3*a+b)*a+3*b))
Ellipse Perimeter
There is working MATLAB code available here. I replicate that below in case that link ever goes dead. Credits are due to the original author.
This code assumes that the major axis is a line segment from (x1, y1) to (x2, y2) and e is the eccentricity of the ellipse.
a = 1/2*sqrt((x2-x1)^2+(y2-y1)^2);
b = a*sqrt(1-e^2);
t = linspace(0,2*pi, 20);
X = a*cos(t);
Y = b*sin(t);
w = atan2(y2-y1,x2-x1);
x = (x1+x2)/2 + X*cos(w) - Y*sin(w);
y = (y1+y2)/2 + X*sin(w) + Y*cos(w);
plot(x,y,'o')
axis equal

Resources