Moving vertex along bisector to set a specific angle - math

I've got a three nodes A, B, C which create an angle α.
Question: how to find a position of B' (x,y coordinates) which is effectively a shift of B along α bisector, that AB'C angle is equal to α+5°

Here (with bisector) simpler solution is possible.
Angle BCB' is 2.5 degrees
Side BB' of triangle BCB' might be calculated using Law of Sines as
Len(BB') = Len(BC) * sin(2.5) / sin(alpha/2+2.5)
Unit bisector vector
bis = BC/Len(BC) + BA/Len(BA)
bis = bis / Len(bis)
B' coordinates
B' = B + bis * Len(BB')

I've actually just found the answer to the same problem (from the mathematical point of view), just described slightly differently:
Deform a triangle along vector to get a specific angle

Related

How do I calculate the yaw, pitch, and roll of a point in 3D?

Given a point in 3D space, what are the three angles (e.g. Euler angles) needed to transform a line to point to that object?
Imagine I have a line (or a box) in 3D and I want to transform its heading, pitch, and bank to point to the 3D point from the origin, what values would I use for those angles?
I can't figure out the math to calculate the angles to point to a location such as (1,2,3).
Note: Instead of "yaw, pitch, roll", I'm going to use the conventions "heading, pitch, bank" as defined by 3D Math Primer for Graphics and Game Development by Fletcher Dunn.
Firstly, notice that in a 2D coordinate system, you only need a single angle + magnitude to "point" to any point in 2D.
Similarly, in a 3D coordinate system, you only need two angles + magnitude to "point" to any point in 3D. The last angle ("bank" or "roll") does not affect the location of a point in 3D. Instead it "spins" the arrow that would point to it. If the object is 360 degrees symmetrical, you won't see spin affecting the object at all. If the object is not symmetrical (e.g. an airplane) it will affect the object (e.g. tilting one wing towards the ground and the other towards the sky).
So the original question actually becomes, "how do I find the heading angle, pitch angle, and magnitude to "point" to any point in 3D space?"
You can easily figure this out using trigonometry functions. Imagine we have the point (1,2,3) and we're trying to calculate the heading, pitch, magnitude.
For the following example, let's use this diagram, where the left axis is X, up is Y, and right is Z. The point (1,2,3), then is represented by the blue sphere.
1. Find the magnitude
First, let's find the easiest value, the magnitude. Luckily for us, the magnitude (length) between any two points is easy to find no matter how many dimensions we are in, simply by using the Pythagorean theorem. Since we are in 3D and we're calculating the distance from the origin to our point, our distance formula becomes:
magnitude = sqrt(x*x + y*y + z*z)
Plugging in our actual values:
magnitude = sqrt(1*1 + 2*2 + 3*3)
= 3.7416573868
So our magnitude (or length) is ~3.741.
2. Find the heading
Next, to find the heading, notice that we just care about rotation about the XZ plane, and we don't care about the Y-axis at all. If we were to "flatten" the 3D space into 2D, it becomes trivial to find the heading.
We can draw a triangle that forms a 90 degree angle with the X-axis (red triangle) and then calculate that angle. Recall from trigonometry tan(angle) = opposite / adjacent, and solving for angle, we get angle = arctan(opposite / adjacent).
In this case "adjacent" is a known quantity (redAdjacent = x = 1), and "opposite" is known too (redOpposite = z = 3). Instead of using arctan to solve the equation though, we want to use atan2 since it'll handle all the different cases of x and y for us.
So we have:
heading = atan2(redOpposite, redAdjacent)
Plugging in our actual values:
heading = atan2(3, 1)
= 1.249045772398
so our heading is 1.249 rad, or ~72°.
3. Find the pitch
Finally we need to find the pitch. Similarly to what we did with the heading, we can flatten the the 3D space into 2D along the plane that contains these three points: (A) the origin (0,0,0), (B) our point (1,2,3), and (C) our point as it would project onto the XZ plane (1,0,3) (e.g. by setting 0 for the Y-value).
If we draw a triangle between all 3 of these points, you will notice that they form a right-triangle again (green triangle). We can simply calculate the angle using arctan2 again.
We already calculated the green hypotenuse in step 1 (i.e. the magnitude of our vector):
greenHypotenuse = sqrt(x*x + y*y + z*z)
= 3.7416573868
We also know the opposite of the green triangle is the same as the y-value:
greenOpposite = y
= 2
Using the pythagorean theorem, we can find the length of the adjacent angle:
greenOpposite^2 + greenAdjacent^2 = greenHypotenuse^2
y*y + greenAdjacent^2 = x*x + y*y + z*z
greenAdjacent^2 = x*x + z*z
greenAdjacent = sqrt(x*x + z*z)
Notice that another way to calculate the adjacent length of the green triangle is to notice that redHypotenuse == greenAdjacent, and we could find redHypotenuse using:
redHypotenuse^2 = redAdjacent^2 + redOpposite^2
= x*x + z*z
redHypotenuse = sqrt(x*x + z*z)
Plugging in actual values, we get:
greenAdjacent = sqrt(1*1 + 3*3)
= 3.1622776602
So now that we know the adjacent and opposite lengths of the green triangle, we can use arctan2 again:
pitch = atan2(greenOpposite, greenAdjacent)
= atan2(2, 3.1622776602)
= 0.563942641356
So our pitch is 0.5634 radians, or about 32°.
Conclusion
If you were to draw a line from the origin, with length 3.741, heading 1.249 rad, and pitch 0.564 rad, it would extend from (0,0,0) to (1,2,3).

Panning via normal vector and plane

I have got a camera and the direction it is looking at. Therefore I can create a plane out of this direction vector if I take it as a normal vector. So now I want to move my camera which should be on this plane along the plane. Everything's in 3D but I couldn't come up with an idea how to do so. How can I implement the navigational method of panning - so moving in this specific plane?
To pan your camera to the left and to the right you need to know not only lookAt direction, but also up direction for the camera. Then you can calculate cross product of lookAt and upAxis and this gives you direction to the right, negated vector gives you direction to the left.
Definition: A vector N that is orthogonal to every vector in a plane is called a normal vector to the plane.
An equation of the plane containing the point (x0, y0, z0) with normal vector N = (A, B, C), is A(x − x0) + B(y − y0) + C(z − z0) = 0.
Note: The equation of any plane can be expressed as Ax + By + Cz = D.
This is called the standard form of the equation of a plane. From the eqn you can get any other point you want on the plane.
Example: A plane passing through the point P = (1, 6, 4) and the normal vector, R = (2, - 3, - 1). Then the eqn is,
2(x-1) - 3(y-6) - (z-4) = 0
=> 2x - 3y - z = -20

Find a vector tangent to a circle

I need to move a point by vectors of fixed norm around a central circle.
So to do this, I need to calculate the circle tangent vector to apply to my point.
Here is a descriptive graph :
So I know p1 coordinates, circle radius and center, and the vector norm d. I need to find p2 (= finding the vector v orientation).
I put on the graph some ideas I got to find it : p1' is p1 projected on the circle. And t is the tangent vector to C in p1'.
That should be easy, but I'm too weak in maths to figure how to implement this. So I would like an idea of the implementation this (language agnostic is okay, javascript is cool).
Extra cool if you can also get me how to implement clockwise and counter clockwise movement with this.
Edit : Obtained this
let vx = cx - p1x,
vy = cy - p1y,
norm = Math.sqrt((vx * vx) + (vy * vy)),
p2x = p1x - (vy * d / norm),
p2y = p1y + (vx * d / norm);
But there is still a quirk : using this on time, the point is slowly getting away from the center of the circle, performing a spiral.
Obtain vector Center of circle - point P1. Let's call this vector
v1.
Tangent vector 't' is perpendicular to v1. If v1=(vx, vy) then
t=(-vy,vx) . Just swap values and a sign (I wrote -vy, it could also be -vx, but not both -vy,-vx).
Setting one direction or the order is just using t2= -t1= (vy, -vx), or (-vy, vx)
For movements you must use normalized (||v|| = 1) vectors.

Rectangle's dimensions, given only the top left and bottom right coordinates, and rotation angle

I have a rectangle that has had a rotation applied. I know the rotation angle, and the top left and bottom right coordinates.
My question is, how do I calculate the dimensions of the rectangle, given these three pieces of information?
If your rotation is in terms of a center point on the rectangle, first you have to get the TL and BR relative to that origin.
Let A,B,C,D be the four vertices TL,TR,BR,BL.
You are trying to find TR and BL which would be B and D.
B_x = C_x*Cos(a) - A_y*Sin(a)
B_y = C_x*Sin(a) + A_y*Cos(a)
Likewise
D_x = A_x*Cos(a) - C_y*Sin(a)
D_y = A_x*Sin(a) + C_y*Cos(a)
Think about what they would be before the rotation. You would just use components of A and C to define B and D. The above just comes from multiplying that by the rotation matrix. Where a is the angle.
If the rotation has already been applied to A and B then get the original points before the rotation which is simply the transpose of the rotation matrix:
A'_x = A_x*Cos(a) + A_y*Sin(a)
A'_y = -A_x*Sin(a) + A_y*Cos(a)
Likewise for C
Then use A' and C' in the first set of equations to find the resulting points with rotation.
If you are just interested in length and width, A' and C' will suffice:
width = C'_x - A'_x
Height = A'_y - C'_y

Rotation matrix that minimizes distance

Let's say I have two points in 3D space (a and b) and a fixed axis/unit vector called n.
I want to create a rotation matrix that minimizes the euclidan distance between point a (unrotated) and the rotated point b.
E.g:
Q := matrix_from_axis_and_angle (n, alpha);
find the unknown alpha that minimizes sqrt(|a - b*Q|)
Btw - If a solution/algorithm can be easier expressed with unit-quaternions go ahead and use them. I just used matrices to formulate my question because they're more widely used.
Oh - I know there are some degenerated cases ( a or b lying exactly in line with n ect.) These can be ignored. I'm just looking for the case where a single solution can be calculated.
sounds fairly easy. Assume unit vector n implies rotation around a line parallel to n through point x0. If x0 != the origin, translate the coordinate system by -x0 to get points a' and b' relative to new coordinate system origin 0, and use those 2 points instead of a and b.
1) calculate vector ry = n x a
2) calculate unit vector uy = unit vector in direction ry
3) calculate unit vector ux = uy x n
You now have a triplet of mutually perpendicular unit vectors ux, uy, and n, which form a right-handed coordinate system. It can be shown that:
a = dot(a,n) * n + dot(a,ux) * ux
This is because unit vector uy is parallel to ry which is perpendicular to both a and n. (from step 1)
4) Calculate components of b along unit vectors ux, uy. a's components are (ax,0) where ax = dot(a,ux). b's components are (bx,by) where bx = dot(b,ux), by = dot(b,uy). Because of the right-handed coordinate system, ax is always positive so you don't actually need to calculate it.
5) Calculate theta = atan2(by, bx).
Your rotation matrix is the one which rotates by angle -theta relative to coordinate system (ux,uy,n) around the n-axis.
This yields degenerate answers if a is parallel to n (steps 1 and 2) or if b is parallel to n (steps 4, 5).
I think you can rephrase the question to:
what is the distance from a point to a 2d circle in 3d space.
the answer can be found here
so the steps needed are as following:
rotating the point b around a vector n gives you a 2d circle in 3d space
using the above, find the distance to that circle (and the point on the circle)
the point on the circle is the rotated point b you are looking for.
deduce the rotated angle
...or something ;^)
The distance will be minimized when the vector from a to the line along n lines up with the vector from b to the line along n.
Project a and b into the plane perpendicular to n and solve the problem in 2 dimensions. The rotation you get there is the rotation you need to minimize the distance.
Let P be the plane that is perpendicular to n.
We can find the projection of a into the P-plane, (and similarly for b):
a' = a - (dot(a,n)) n
b' = b - (dot(b,n)) n
where dot(a,n) is the dot-product of a and n
a' and b' lie in the P-plane.
We've now reduced the problem to 2 dimensions. Yay!
The angle (of rotation) between a' and b' equals the angle (of rotation) needed to swing b around the n-axis so as to be closest to a. (Think about the shadows b would cast on the P-plane).
The angle between a' and b' is easy to find:
dot(a',b') = |a'| * |b'| * cos(theta)
Solve for theta.
Now you can find the rotation matrix given theta and n here:
http://en.wikipedia.org/wiki/Rotation_matrix
Jason S rightly points out that once you know theta, you must still decide to rotate b clockwise or counterclockwise about the n-axis.
The quantity, dot((a x b),n), will be a positive quantity if (a x b) lies in the same direction as n, and negative if (a x b) lies in the opposite direction. (It is never zero as long as neither a nor b is collinear with n.)
If (a x b) lies in the same direction as n, then b has to be rotated clockwise by the angle theta about the n-axis.
If (a x b) lies in the opposite direction, then b has to be rotated clockwise by the angle -theta about the n-axis.

Resources