I'm working on a project to solve triangles, but I cant seem to figure out how to get the inverse of sine, I've already set up switching from radians to degrees in my program I just need inverse operators.
Simply use Math.asin:
Math.asin(opposite / hypotenuse);
Math.sin(x) takes a radian and outputs a range [-1 , 1].
Math.asin(x) takes a range [-1 , 1] and outputs a radian value.
To convert these radian values, use these two functions:
degreeToRadian = d => d * Math.PI * 180 ** -1
radianToDegree = r => r * 180 * Math.PI ** -1
For example:
Math.sin(degreeToRadian(30)).toFixed(3) * 1
results -> 0.5
or:
radianToDegree(Math.asin(0.5)).toFixed(3) * 1
results -> 30
Related
Referring to the first diagram, I am trying to copy the three objects, looking at them from an arbitrary angle(A1). The distance between where I'm and the first object does not matter just the relative location of the object to one another.
In the second diagram, I select a point to copy these objects, facing another arbitrary angle(B1).
Angle (C1) shows the approximate position of -90 degrees.
I can get this to work if A1 = 0,90,180,270 and even 45,135 etc but the equations I come up with only work for 0 and 180 or 90 and 270. I have to modify them to work in those directions by changing a hardcoded offset angle and putting/removing a negative sign before the offset.
I'm doing this is javascript (and its Minecraft) usually I can figure out this but I have been working on it for weeks.
Here is some pseudo-code that works some of the time in certain right-angle directions. I have updated this to be more accurate, the 1x and 2x are the blocks x coordinate, etc. - everything is relative from the (1) block.
Minecraft's coordinate system is a little different from normal - 0 is south, +90 is west, 180 is north, 270 is east.
the only difference is that I am making negative az, ax.
// works for north/south looking - A1 is either 180/0 , B1 can be anything
var x = 1x - 2x;
var z = 1z - 2z;
var direction = Math.atan2(z1, x1);
var L1 = Math.sqrt(Math.pow(x1, 2) + Math.pow(z1, 2));
var az = Math.round(L1 * Math.sin((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
var ax = Math.round(L1 * Math.cos((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
// works for east/west looking - A1 is either 90/270 , B1 can be anything
var x = 1x - 2x;
var z = 1z - 2z;
var direction = Math.atan2(z1, x1);
var L1 = Math.sqrt(Math.pow(x1, 2) + Math.pow(z1, 2));
var az = -Math.round(L1 * Math.sin((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
var ax = -Math.round(L1 * Math.cos((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
First diagram
Second diagram
I recently came across a YouTube video that discussed handling GPS coordinates by using space filled curves. There was a formula provided to accomplish this so I've decided to try and replicate it, however I have not been able to figure out how to get to the same result using JavaScript.
The formula was as follows:
Scale Latitude and longitude to use 16 available bits each:
scaled_x = (-122.4012 + 180) / 360 * 2 ^ 16 // result = 10485
scale_y = (37.7839 + 90) / 180 * 2 ^ 16 // result = 46524
Video Reference
I've tries several ways of writing the formula and my results are far off from what I should be getting based on what was shown in the presentation. Either the presentation was inaccurate or I've not landed on the correct way of getting to this.
Here are some of my attempts, all fail.
Using Pow
base = Math.round((lat + 180) / 360);
scale = Math.pow(base * 2, 16); // Result = 0
Exact Formula
base = Math.round((lat + 180) / 360 * 2 ^ 16); // Result = 16
Inline Power
base = Math.round((lat + 180) / 360 * Math.pow(2, 16)); // Result = -22282
Does anyone know how this formula needs to be structured in JavaScript to get the expected outcome?
base = Math.round((lat + 180) / 360);
scale = Math.pow(base * 2, 16)
This doesn't work because you're rounding the value before multiplying it by 216 -- so it will round to either 0 or 1. This is not what you want.
base = Math.round((lat + 180) / 360 * 2 ^ 16);
In Javascript -- and many other languages -- ^ is used for bitwise XOR, not exponentiation. 2 ^ 16 is 18, not 65536.
base = Math.round((lat + 180) / 360 * Math.pow(2, 16));
This looks correct. The result you've quoted isn't right for lat = -122.4012, though -- did you leave out the + 180, perhaps?
I am trying to get sin and cos of an angle that is 9.590124942537262.
In Javascript I would do it like that:
var a = Math.sin(9.590124942537262);
var b = Math.cos(9.590124942537262);
The results would be:
a == -0.16459459028073223
b == -0.9863613034027227
If I do the same operation in PHP like this:
$a = sin(9.590124942537262 * M_PI / 180); // ≈ 0.16737916966136 rad
$b = cos(9.590124942537262 * M_PI / 180);
I get these results:
$a == 0.16659953926461
$b == 0.9860246414349
Question is: how do I make these operations uniform, so that PHP returns correct value with a minus sign? I tried rounding my angle but that didn't help.
Both PHP and JavaScript's trigonometry functions work in radians
In your PHP example, you are trying to convert from degrees to radians, because you're actually supplying radians to be converted into radians, you're just adding Pi radians, or 180 degrees, hence why you get the negative result.
You should be able to do the code in each language with the same parameter:
Math.sin(9.590124942537262);
Math.cos(9.590124942537262);
sin(9.590124942537262);
cos(9.590124942537262);
I have the following function, to find the angle between 3 points.
(Where a point is defined as an array containing the x position as its first element and the y position as its second element, and the angle to measure is the angle created when a line is drawn through all three points.)
findAngle: function(a, b, c) {
var ab = Math.sqrt(Math.pow(b[0] - a[0], 2) + Math.pow(b[1] - a[1], 2));
var bc = Math.sqrt(Math.pow(b[0] - c[0], 2) + Math.pow(b[1] - c[1], 2));
var ac = Math.sqrt(Math.pow(c[0] - a[0], 2) + Math.pow(c[1] - a[1], 2));
var o1 = (bc * bc + ab * ab - ac * ac) / (2 * bc * ab);
var o2 = Math.acos(o1);
var o3 = o2 * (180 / Math.PI);
return o3;
}
However, this only ever returns angles between 0 and 180 degrees. How can I have it return values between 0 - 180 degrees, and values between 180 and 360 when the angle is in fact obtuse?
Use atan2 function that has two arguments and returns result in range -Pi..Pi (add 2*Pi to negative angles if needed)
angle = Math.atan2(crossproduct(c-b,b-a), dotproduct(c-b,b-a))
where
crossproduct(c-b,b-a) = (c.x-b.x)*(b.y-a.y) - (c.y-b.y)*(b.x-a.x)
dotproduct(c-b,b-a) = (c.x-b.x)*(b.x-a.x) + (c.y-b.y)*(b.y-a.y)
it's probably not the right place to post this but i don't know where else to post it.
i have 5 lines (d1 -> d5) equally distributed from each other in 3d perspective, i have the values of (a) angle, (d1) and (b5). i need to calculate (b2, b3, b4, d2, d3, d4, d5) with jquery.
i can calculate d5 with:
d5 = d1 - ( b5 * Math.tan(a))
but i have no idea how to calculate b2, b3 and b4. (d1 is divided into 4 identical segaments (s))
any help would be appreciated.
What you're looking for is a projective scale. The easiest way to do this computationally is to use homogenous coordinates, take a rectangle (like the one in the first picture below) on which V is "infinitely far to the right" and find a projective transformation that maps this rectangle to the trapezium in the second picture. The vertices of the rectangle are (0|0), (0|d1), (b5|d1), (b5|0) and the corresponding vertices of the trapezium are (0|0), (0|d1), (b5|d5), (b5|0).
Since these are four points of which no three are collinear, we can find a unique matrix (up to scaling) M for this transformation. After some maths, it turns out that this matrix is:
[d1*b5,0,0]
[0,b5*d5,0]
[d1-d5,0,b5*d5]
If you want to find the coordinates b3 and d3, for instance, you can multiply this matrix with homogenous coordinates of the point in the middle of the line, i.e. the vector (0.5*b5,d1,1)^T and you get the homogenous coordinates of the point (b3|d3), which can be converted into Euclidean coordinates by dehomogenisation, i.e. dividing the first two components by the third.
In general, if you have two points (b1|d1) and (bn|dn) and want to know the coordinates of n-2 equidistant points inbetween on a projective scale like this, you can compute the coordinates bi and di as like this (in your case, n would be 5, of course):
let M := matrix [[d1*bn, 0, 0], [0, bn*dn, 0], [d1-dn, 0, bn*dn]]
let v := ((i-1)/(n-1)*bn, d1, 1)
let (x,y,z) := M*v
let bi := x/z and di := y/z
As you see, this is a simple algorithm for computing the coordinates of these projectively equidistant points, and it generalises nicely to arbitrary numbers of points.
If you'd rather have a closed formula, you can compute the bi and di directly as:
let bi := (bn*d1*(i-1))/(dn*n+(d1-dn)*i-d1)
let di := d1*dn*(n-1)/(dn*n+(d1-dn)*i-d1)
First we need to calculate what the length of the adjacent side of the whole triangle d1->v->c is (the left vertical side of it):
tan(Θ) = opposite / adjacent
opposite * tan(Θ) = adjacent
adjacent = opposite * tan(Θ)
adjacent = d1 * tan(a)
Next thing we need is to know how much off the ground each line from v is when it gets to line d1. Given that variable s is the same for all divisions and assuming N dividing segments (in this case 3), our counter is i that starts from 1 and goes to N:
opposite(i) = i * (d1 / N)
Now we need the angle that line from v to each marker s makes:
tan(Θi) = opposite / adjacent
Θi = arctan(opposite / adjacent)
Θi = arctan(opposite(i) / adjacent)
Θi = arctan((i * (d1 / N)) / (d1 * tan(a)))
Using some geometry/trig we can say that angle going from d1 through point c to top of d5 is (90° - a). We will call this angle a'
a' = 90° - a
Law of sines tells us that:
A' / sin(a') = opposite(i) / sin(b')
so now we solve for A' since we need some help with getting the dimensions of the orange square:
A' = (opposite(i) * sin (a')) / sin(b')
since b' = (a + Θi) this turns into:
A' = (opposite(i) * sin (90° - a)) / sin(a + Θi)
Same thing applied but solving for h in the orange triangle (see picture):
h / sin(90°-Θi) = A' / sin(90°)
h = (A' * sin(90°-Θi)) / sin(90°)
b2 = h
Putting it all together (hopefully without copy/paste mistakes on my part) and without simplifications:
b2 = (((( i * (d1 / N)) * sin (90° - a)) / sin(a + Θi)) * sin(90° - arctan((i * (d1 / N)) / (d1 * tan(a))))) / sin(90°)
Now rinse/repeat for each value of i and turn into code (I would have done that but I'm too tired) :)