简体   繁体   English

C#旋转问题

[英]c# rotation problem

I have 3 particles and one of them is the center particle. 我有3个粒子,其中一个是中心粒子。 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. 我想使用公式q'=Θq+ p相对于中心粒子旋转其他两个粒子(存储在粒子列表中),其中q'是旋转粒子的新位置,Θ是方向角,p是中心粒子。 The initial position of other two particles is stored in initialParticlePosition list. 其他两个粒子的初始位置存储在initialParticlePosition列表中。 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. 我想我应该将范围设为[-pi,pi)或类似的东西。 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;
         }
}

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, eg you could accept this answer ) (您应开始将有助于回答的答案标记为答案,单击左侧投票下方的对勾标记,例如,您可以接受此答案

Edit: Optimized the methods a bit. 编辑:稍微优化了方法。

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. 假设p1,p2和p3是Vector2,而p2和p3绕着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. Matrix.Create ...()方法将为您调用两个触发函数。

edit. 编辑。 the Matrix & Vector2 structures & methods are XNA specific but included here because that's what the OP tagged his Q with. Matrix和Vector2的结构和方法是XNA特定的,但在此包含在其中,因为这就是OP标记其Q的原因。

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. 您可能会怀疑,点积和Acos的组合只能为您提供180度范围内的角度。

Instead, use Atan2 on your unit vector to get a full range of angles from -pi to pi. 而是在单位向量上使用Atan2,以获得从-pi到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. 如果您的Y轴在向下方向上为正,则可能需要取消Y项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM