Spherical Distance in JavaScript - javascript

I need to find the Spherical Distance of two coordinates using Javascript. I am using Wolfram a lot for this project and found this formula d=cos^(-1)(P·Q) [reference: http://mathworld.wolfram.com/SphericalDistance.html]. So I know that P·Q is the dot product of the two coordinates in question. This leads to finding the dot product which I found as DotProduct = (x1*x2 + y1*y2 + z1*z2) [reference: http://en.wikipedia.org/wiki/Dot_product]. So I put together the following method and get NaN (Not a Number) every time.
function ThreeDimensionalDistance(x1,y1,z1,x2,y2,z2){
return Math.acos(x1*x2 + y1*y2 + z1*z2);
}
Here are two sets of sample data I use and I can't figure out why I get NaN. Am I missing something small, do I need to convert my numbers to something for them to work with arc cos? Thank you in advance for any help.
Sample 1
X:-1.7769265970284516,Y:-5.129885707200497,Z:-2.554761143401265
X:-0.8336414256732807,Y:-1.9876462173033347,Z:5.599491449072957
Distance: NaN
Sample 2
X:-0.8336414256732807,Y:-1.9876462173033347,Z:5.599491449072957
X:0.8447772905770565,Y:4.252407300473133,Z:4.147696165367961
Distance: NaN

I've done some math, so try the following out:
function threeDimensionalDistance(x1, y1, z1, x2, y2, z2) {
// Assume that the points are on the same sphere
var radius = Math.sqrt(x1 * x1 + y1 * y1 + z1 * z1);
// Calculate normalized spherical distance
var dotProduct = x1 * x2 + y1 * y2 + z1 * z2;
var normalizedDistance = Math.acos(dotProduct / (radius * radius));
// Calculate actual distance
var distance = normalizedDistance * radius;
return distance;
}
One minor change that I made was renaming your method to begin with a lowercase letter, to follow standard JavaScript style guidelines.

Related

Intersection of two Moving Objects

I'm trying to use the answer provided here: Intersection of two Moving Objects with Latitude/Longitude Coordinates
But I have some questions..
What is this angle:
var angle = Math.PI + dir - target.dir
I was thinking that the angle that should be used in the law of cosines is already "alpha or target.dir".. What is that line doing? Also in these two steps:
var x = target.x + target.vel * time * Math.cos(target.dir);
var y = target.y + target.vel * time * Math.sin(target.dir);
Shouldn't the code be using the angle between x- or y-axis and the target velocity vector? Why is the author using alpha here?
What is this angle:
var angle = Math.PI + dir - target.dir
The variable named angle is indeed the angle alpha. Because the direction dir is the direction from chaser to target, and we need it the other way round for this calculation, we add π to it before we subtract target.dir.
Maybe using the word angle as a variable name was a bit vague; I'll change it to alpha, the name I used for this angle in the images.
Shouldn't the code be using the angle between x- or y-axis and the target velocity vector? Why is the author using alpha here?
var x = target.x + target.vel * time * Math.cos(target.dir);
var y = target.y + target.vel * time * Math.sin(target.dir);
We are indeed using target.dir, which is the direction of the target, i.e. the angle between the x-axis and the target vector, to calculate the coordinates of the interception point, and not the angle alpha.

Get X,Y coordinates from Angle & Distance ( Incorrect values using Math.cos() & Math.sin() )

I've read all accepted answers on this topic and repeated exactly the logic used in them but my results seem to be skewed and 'random'.
I have correctly collected the X,Y and degrees from the center object as shown here:
console.log('deg' + degrees + ' - ' + 'x' + parseInt(x) + ', y' + parseInt(y));
Note: The X,Y grid spans much further out of the viewport that is shown. Technically the grid is unlimited in size. We are in our own specific X,Y coordinate in this grid space.
Now I want to calculate an X,Y coordinate that is 1000 pixels away from the click position. Here is an example of what I'm trying to achieve:
The logic I found elsewhere should be as simple as such:
x = 1000 * Math.cos(degrees);
y = 1000 * Math.sin(degrees);
console.log('deg' + degrees + ' - ' + 'x' + parseInt(x) + ', y' + parseInt(y));
The result is as such:
The issue: Clearly in the image above, the X,Y coordinates are way off to what I should be expecting. They are much too low and change too often to random numbers.
The grid for this layout is as shown below:
Note: The X axis goes positive to the left. Is this the underlying issue or is it my original logic that is wrong?
Thank you for considering my question
I've tried the suggested code. Here are my results.
Result from #MBo's now old answer:
new_x = 1000 * Math.cos(degrees * Math.PI / 180);
new_y = 1000 * Math.sin(degrees * Math.PI / 180);
The results look a lot cleaner and less 'random' however the end X,Y go in the incorrect direction and distance
and change too often
Trigonometric functions work with radians rather than degrees, so calculate arguments like this:
Math.cos(degrees * Math.PI / 180);
Math.sin(degrees * Math.PI / 180);
To make rotation around some point, add these values to its coordinates
x = center_object_x + Math.cos(degrees * Math.PI / 180);
y = center_object_y + Math.sin(degrees * Math.PI / 180);

Floating point number precision or algorithmic error in JavaScript

I tried to implement in JavaScript rotation around point, using rotation matrix, but for some reason I got some unexpected results - instead of moving around a point, my figure was moving along a line. Here I provide completely reproducible example, which demonstrates that after rotation distance between a rotating point and the center changes. Here it is:
var alpha = 0.10146071845187077;
var cos_ = Math.cos(alpha);
var sin_ = Math.sin(alpha);
var center = [4861165.687852355,7606554.432771027];
var pointBefore = [4847712.770874163, 7610682.032298427];
var dist1, dist2, x1, y1, x2, y2, pointAfter = [];
// 1. substract + 2. rotate + 3. get back
// 1.
x1 = pointBefore[0] - center[0];
y1 = pointBefore[1] - center[1];
// 2.
x2 = cos_ * x1 - sin_ * y1;
y2 = sin_ * x1 + cos_ * y1;
// 3.
pointAfter[0] = x2 + center[0];
pointAfter[1] = y2 + center[1];
// Check distances
dist1 = Math.sqrt(Math.pow(x1, 2) + Math.pow(y1, 2));
dist2 = Math.sqrt(Math.pow(pointAfter[0] - center[0], 2) +
Math.pow(pointAfter[1] - center[1], 2));
console.log(JSON.stringify({dist1: dist1, dist2: dist2}));
// -> {"dist1":14071.888753138577,"dist2":14071.88875313881}
I hope, I made some errors in math, but I cannot see them.
Inaccuracy is due to the fact how floating point numbers are stored:
Is floating point math broken?
Basically, it's impossible to store irrational numbers and high precision real numbers in the fixed space of 64bits so there will be rounding errors which become significant after many operations. Think of the number 2/3, you cannot represent it accurately no matter the precision.
A possible solution is to either calculate with whole numbers only when possible or round the results after each operation.

UserInput Is Messing Up a Function

I was trying to make something that told you the intersection points of two circles. Where I put in the centers of the circles and the radius. (I got the intersection function from stackoverflow: here). I am trying to add the user input but when ever I change the static number inside the code to a user input (either through prompt or html input), the function breaks and the alert sends me an unfinished answer and an Nan.
Here is the coding so far (without user input):
<html>
<button onclick="button()">Test</button>
<script>
var x0 = 3;
var y0 = 0;
var r0 = 3;
var x1 = -1;
var y1 = 0;
var r1 = 2;
function button() {
intersection(x0, y0, r0, x1, y1, r1)
function intersection(x0, y0, r0, x1, y1, r1) {
var a, dx, dy, d, h, rx, ry;
var x2, y2;
/* dx and dy are the vertical and horizontal distances between
* the circle centers.
*/
dx = x1 - x0;
dy = y1 - y0;
/* Determine the straight-line distance between the centers. */
d = Math.sqrt((dy*dy) + (dx*dx));
/* Check for solvability. */
if (d > (r0 + r1)) {
/* no solution. circles do not intersect. */
return false;
}
if (d < Math.abs(r0 - r1)) {
/* no solution. one circle is contained in the other */
return false;
}
/* 'point 2' is the point where the line through the circle
* intersection points crosses the line between the circle
* centers.
*/
/* Determine the distance from point 0 to point 2. */
a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
/* Determine the coordinates of point 2. */
x2 = x0 + (dx * a/d);
y2 = y0 + (dy * a/d);
/* Determine the distance from point 2 to either of the
* intersection points.
*/
h = Math.sqrt((r0*r0) - (a*a));
/* Now determine the offsets of the intersection points from
* point 2.
*/
rx = -dy * (h/d);
ry = dx * (h/d);
/* Determine the absolute intersection points. */
var xi = x2 + rx;
var xi_prime = x2 - rx;
var yi = y2 + ry;
var yi_prime = y2 - ry;
var list = "(" + xi + ", " + yi + ")" + "(" + xi_prime + ", " +
yi_prime + ")"
alert(list);
}
}
</script>
</html>
When I change anyone of the variables that apart of the circle into user input like:
var x0 = prompt("X cord of circle 1");
The alert comes up as: (3-2.6250, -1.4523687548277813)(NaN, 1.4523687548277813)
and without the user input (shown in the large code block) it comes out as: (0.375, -1.4523687548277813)(0.375, 1.4523687548277813). Which is the correct answer.
Can anyone tell me what I am doing wrong or what is going on?
Prompt will take the user input as a string. To convert it to an integer for math jazz, use parseInt.
var x0String = prompt("X cord of circle 1");
var x0 = parseInt(x0String);
JavaScript should "convert" numeric string to integer if you perform calculations on it since JS is weakly typed, but it is good practice and you can avoid some pitfalls by parsing the integer value from a string yourself.
Your prompt returns a string, but you can't do math on a string. Try converting it to a number:
var x0 = Number(prompt("X cord of circle 1"));
As Daniel pointed out it's always better to change the string to a number if you need it as a number. It seemed really confusing, why the program was not working, until I found that x0 is used twice.
The reason the program was returning NaN is because when using the + operator, the number is converted into a string not a number.
That happens here: x0 + (dx * a/d);
What happens then is that a negative number is added to the string creating something like: 2-2
As you might expect the value can no longer be converted into a number, thus returning NaN, when we try to minus it later.

Javascript: Find point on perpendicular line always the same distance away

I'm trying to find a point that is equal distance away from the middle of a perpendicular line. I want to use this point to create a Bézier curve using the start and end points, and this other point I'm trying to find.
I've calculated the perpendicular line, and I can plot points on that line, but the problem is that depending on the angle of the line, the points get further away or closer to the original line, and I want to be able to calculate it so it's always X units away.
Take a look at this JSFiddle which shows the original line, with some points plotted along the perpendicular line:
http://jsfiddle.net/eLxcB/1/.
If you change the start and end points, you can see these plotted points getting closer together or further away.
How do I get them to be uniformly the same distance apart from each other no matter what the angle is?
Code snippit below:
// Start and end points
var startX = 120
var startY = 150
var endX = 180
var endY = 130
// Calculate how far above or below the control point should be
var centrePointX = ((startX + endX) / 2);
var centrePointY = ((startY + endY) / 2);
// Calculate slopes and Y intersects
var lineSlope = (endY - startY) / (endX - startX);
var perpendicularSlope = -1 / lineSlope;
var yIntersect = centrePointY - (centrePointX * perpendicularSlope);
// Draw a line between the two original points
R.path('M '+startX+' '+startY+', L '+endX+' '+endY);
Generally you can get the coordinates of a normal of a line like this:
P1 = {r * cos(a) + Cx, -r * sin(a) + Cy},
P2 = {-r * cos(a) + Cx, r * sin(a) + Cy}.
A demo applying this to your case at jsFiddle.

Categories

Resources