#How does Vec2.rotate work?

3 messages · Page 1 of 1 (latest)

livid salmon
#

So, I was looking for a function to rotate a 2D vector around an angle. I could write this myself, but it's a pretty basic thing so I figured it might already exist. An conveniently, there is a function on Vec2 called rotate... But what it does is very confusing. It takes rhs: Vec2 as an argument, and the description says:

Returns rhs rotated by the angle of self. If self is normalized, then this just rotation. This is what you usually want. Otherwise, it will be like a rotation with a multiplication by self’s length.

So first of all, it "rotates" the vector passed in, NOT the vector it's called on, which seems backwards. Secondly, what does it even mean to rotate a Vec2 by a Vec2? A 2D vector can only rotate around one axis. It says it rotates by the angle of self, so does that mean it rotates it by the angular offset of self from one of the main axes? Which one? And if self isn't a unit vector, it multiplies the rotation by self's length?

So I looked at the implementation. Which is this:

    pub fn rotate(self, rhs: Self) -> Self {
        Self {
            x: self.x * rhs.x - self.y * rhs.y,
            y: self.y * rhs.x + self.x * rhs.y,
        }
    }

Not sure exactly what this does, but it doesn't look like rotation as I understand it. Maybe it's a much more efficient special case of rotation? But if what I have is an angle, not a unit vector already at the appropriate angle, then I still need to call trig functions to generate that vector, so I lose all those efficiency gains, and doing that is almost as complicated as just rotating the vector myself.

I may be misunderstanding things here, but it SEEMS like the rotate function should just take an angle and rotate by that angle, accepting that it'll need to call some trig functions. And if what this rotate function is doing is useful, it should be renamed to something that better reflects the special case it handles.

livid salmon
#

In writing my own rotation function, I realized it actually DOES look very similar:

fn rotate(vec: Vec2, angle: f32) -> Vec2 {
    let sin_angle = angle.sin();
    let cos_angle = angle.cos();
    Vec2::new(
        vec.x * cos_angle - vec.y * sin_angle,
        vec.x * sin_angle + vec.y * cos_angle
    )
}

So given this, I could just call vec.rotate(Vec2::new(angle.cos(), angle.sin())). I still think this is a really weird API, though.