How do I rotate a triangle such that all of its points have the same z value

Hi, everyone.
Kinda noob question here but I’m having trouble figuring this out.
I have a triangle object that I need to rotate such that all points ends up having the same z values with respect to one of its points. Or in other words I keep one of its points fixed and pivot the other points around it till they have the same z value as the pivot point. For simplicity lets just say the triangle needs to end up with all of its z value equating to zero. I need to maintain the shape so I can’t project and deform the triangle.

My initial attempt:
//I’m pivoting about point2 so all point vectors have been sub(point2)
//For simplicity sake I made point1 and point3 have the same non zero Z value

triangle = new Triangle(point1, point2, point3);
normal = new Vector3();
triangle.getNormal(normal);

zPlane = new Vector3(0, 0, 1)
rotationAxis = zPlane.clone().cross(normal);
rotationAngle = Math.acos(zPlane.dot(normal));

point1.applyAxisAngle(rotationAxis, rotationAngle).add(point2)
point3.applyAxisAngle(rotationAxis, rotationAngle).add(point2)

This doesn’t seem to work for me, the rotation axis is correct but the angle seems to be wrong. The resulting rotation does not end up with same z values.
In reality the triangle has random z valies, point1 and point3 don’t have the same Z so I need to do multiple rotations. Would appreciate it if someone can help with the full function for this.

Thanks

You can use the points to define 2 edges… b-a and c-b… Then .cross those 2 vectors to get the face normal, and then… find the angle between 0,0,1 and that face normal. and then … construct a 3rd vector as the cross between 0,0,1 and the face normal… This vector is the axis, and the angle is
What we computed… and you construct a quaternion from that axis vector and the angle via quaterniom.fromAxisAngle… and .applyquaternion that rotation quaternion on each of the original points.

Isn’t that the same as the example function I provided?
Three.Triangle.getNormal(normal) //gets the face normal
rotationAxis = zPlane.cross(normal);
rotationAngle = Math.acos(zPlane.dot(normal));

And three.Vector3 has applyAxisAngle() which is more direct than creating a quaternion and applying that to the vector3. I assume its the same.

Bump
Anyone?
I might be misunderstanding the function of applyAxisAngle because it is not returning the result I expect

let point1 = new Vector3(-1,2,3)
let point2 = new Vector3(0,0,0)
let point3 = new Vector3(1,2,3)
	
const triangle = new Triangle(point1, point2, point3);
const normal = new Vector3();
triangle.getNormal(normal);
	
let zPlane = new Vector3(0, 0, 1)
const rotationAxis = zPlane.clone().cross(normal); 
const rotationAngle = -Math.acos(zPlane.dot(normal)); 
point1.applyAxisAngle(rotationAxis, rotationAngle)
// point1 = Vector3 {x: -1, y: -0.6934920359958369, z: 3.459761946006245} 
// -rotationAngle 
// point1 = {x: -1, y: 3.4603541178503168, z: 0.6905311767754756} 

As you see the resulting z is not equal to 0 in either rotation direction. I don’t know what I’m doing wrong here.

Would you accept an idea that uses no rotation whatsoever?

If “yes” see a demo here: https://codepen.io/boytchev/full/PoMPWKB

  • reload the page for another random triangle
  • ABC is the original, A₂BC₂ is the new triangle
  • calculation of A₂ and C₂ is in lines 61-69

Here is an exceptionally ugly illustration of the idea - do not rotate the triangle, just recreate it by knowing point B, the lengths of AB and BC, and the angle at B:

2 Likes

Thanks!
I will look into this.

I can use this method tho it seems it doesn’t preserve symmetry for symmetrical triangles
For example for the triangle
Vector3(-1,2,3) , Vector3(0,0,0), Vector3(1,2,3)
I would like the resultant triangle pivoting about (0,0,0) to be
Vector3(-1,0,0) , Vector3(0,0,0), Vector3(1,0,0)

Also wondering why the code I used didn’t work as intended.

I didn’t know there is an extra requirements like symmetry.

Also, most likely I misunderstand the issue, because I cannot imagine what rotation will transform triangle [(-1,2,3) , (0,0,0), (1,2,3)] into segment [(-1,0,0) , (0,0,0), (1,0,0)].

You can dot the ab ac edges. You can get the length of ab and ac edges. Then you can put that same triangle anywhere you want.

Well symmetry was not really a requirement. I was just testing my code with such points. Wouldn’t rotating about the x-axis transform it as mentioned?

This is not the same triangle (it is not a triangle at all).

Oops sorry. I meant Vector3(-1,y’,0) , Vector3(0,0,0), Vector3(1,y’,0) . Whatever the resultant y would be after rotating on the x axis till z=0

Would this make any change:

const rotationAxis = zPlane.clone().cross(normal).normalize();
const rotationAngle = Math.PI-Math.acos(zPlane.dot(normal));

(try it here: https://codepen.io/boytchev/pen/BaXoWQB?editors=0011, change lines 46-52 for other triangles)

1 Like

Yeah it worked. I didn’t think about having to normalize the axis.
Thanks a lot again. I will look into both solutions and see which is more appropriate.

Did you see the PI in the angle?

You calculate the red angle. But the rotation must use the blue angle. The blue angle is the same as the green angle, which is 180°-red; thus the rotation should be 180°-red ( blue = π-red )

1 Like

I didn’t notice yr code since it wasn’t in code markdown. Creating a quat is more efficient that recomputing axis/angle for each point. what you’re doing does look conceptually similar to what I described though. And if you’re doing this to align an object to the ground plane then you want the quaternion anyway… but it wasn’t clear from your post why you wanted to do this very specific sort of operation.
Any background on what the higher level goal is?

Thanks for the illustration. I did originally have the correct angle as you described, but since I didn’t normalize the axis it still gave me the wrong answer.

Yeah sorry. I’m new to all of this and my math is very basic. I saw examples where you create a quat and then apply the quat to the vector, but then I saw that vector3 has an applyaxisangle function which seemed more direct and less code. I assumed it was faster to do just that since it gave the same result anyway. I didn’t benchmark as its just a handful of triangles.

I get a bunch of triangles that are oriented randomly and goal was to just ensure the triangles I get are transformed such that they all have the same z value, with one point of the triangle acting as the pivot.

1 Like

Oo i overlooked that bit of context about one of the points being the rotation origin. I guess you would want to subtract that point from the other points first, before applying this rotation, effectively making that point be 0,0,0, apply the rotation, then add that original point back to all of them.

r.e. making the quaternion being faster… creating a axis angle rotation does calls to Math.sin and Math.cos…

but once you have the quaternion, transforming a point by it is just a bunch of multiplies and adds/subs:

Honestly… its possible that the difference is negligible in your case, now that I look at the code.

Anyway… if you put the problem setup into a glitch of a codepen, i bet that would bait some users into solving it. :wink: these problems can be like catnip.

edit: NVM i see @PavelBoytchev already got the catnip. :wink:

1 Like

Had already subtracted the pivot point vectors. Simple oversight of not normalizing the axis gave me the error which PavelBoytchev pointed out. Thanks for the replies anyways.

1 Like

Why bother with the rotation though. Why not just get the AB AC and angle at A?