0

I have 3 particles and one of them is the center particle. I want to rotate other two particle ( stored in particles list ) relative to the center particle with the formula q' = Θq + p where q' is the new position of the rotated particle, Θ is the orientation angle and p is the position of center particle. The initial position of other two particles is stored in initialParticlePosition list. THe problem is I think the angle I calculate is wrong because of the range. I thing I should take the range as [-pi, pi) or something like this. In some parts it calculates correct but sometimes it is wrong. Can someone help me with this code or give me another method of rotating.

{

         angle = Math.Acos(Vector2.Dot(heading,new Vector2(0,-1) ));

         for (int i = 0; i < 2; i++)
         {
             tempX = (double)initialParticlePositions[i].X * Math.Cos(angle) - (double)initialParticlePositions[i].Y * Math.Sin(angle) + centerParticle.position.x;
             tempY = (double)initialParticlePositions[i].X * Math.Sin(angle) + (double)initialParticlePositions[i].Y * Math.Cos(angle) + centerParticle.position.y;
             particles[i].position.x = tempX;
             particles[i].position.y = tempY;
         }
}
1
  • Run your code with known values for the angle and plot the output on paper. Verify the output by hand. cos and sin should cope with angles outside [-pi,pi] (it's been a while since I did this sort of thing). Commented Jan 11, 2011 at 20:06

3 Answers 3

2

Some methods that might help (angles always in degrees, not rad):

    public static double GetAngle(Vector v)
    {
        return Math.Atan2(v.X, -v.Y) * 180.0 / Math.PI;
    }

    public static Vector SetAngle(Vector v, double angle)
    {
        var angleInRads = angle * (Math.PI / 180.0);
        var distance = v.Length;
        v.X = (Math.Sin(angleInRads) * distance);
        v.Y = -(Math.Cos(angleInRads) * distance);
        return v;
    }

    static public Point RotatePointAroundCenter(Point point, Point center, double rotationChange)
    {
        Vector centerToPoint = point - center;
        double angle = GetAngle(centerToPoint);
        Vector centerToNewPoint = SetAngle(centerToPoint, angle + rotationChange);
        return center + centerToNewPoint;
    }

(You should start marking answers that help as answer, click the checkmark outline below the votes on the left, e.g. you could accept this answer)

Edit: Optimized the methods a bit.

Sign up to request clarification or add additional context in comments.

1 Comment

+1 ... You might provide an explanation of what you're doing. Specifically, that you're translating the point so that it's relative to the origin, doing the rotation, and then translating back.
1

The particle positions that are orbiting can be set with a single line of code each:

Assume p1, p2, & p3 are Vector2s and p2 & p3 are orbiting p1.

p2 = Vector2.Transform(p2 - p1, Matrix.CreateRotationZ(rotationChangeP2)) + p1;

p3 = Vector2.Transform(p3 - p1, Matrix.CreateRotationZ(rotationChangeP3)) + p1;

The Matrix.Create...() method will call the two trig functions for you.

edit. the Matrix & Vector2 structures & methods are XNA specific but included here because that's what the OP tagged his Q with.

Comments

0
angle = Math.Acos(Vector2.Dot(heading,new Vector2(0,-1)));

As you suspect, your combination of dot product and Acos will only give you angles in a 180 degree range.

Instead, use Atan2 on your unit vector to get a full range of angles from -pi to pi.

angle = (float)Math.Atan2((double)heading.Y, (double)heading.X);

You may need to negate the Y term if your Y axis is positive in the down direction.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.