时间:2019-05-09 标签:c#

发布于 2024-10-11 15:46:29 字数 824 浏览 3 评论 0原文

我有 3 个粒子,其中一个是中心粒子。我想使用公式 q' = θq + p 相对于中心粒子旋转其他两个粒子(存储在粒子列表中),其中 q' 是旋转粒子的新位置,θ 是方向角,p 是中心粒子。另外两个粒子的初始位置存储在initialParticlePosition 列表中。问题是我认为由于范围的原因我计算的角度是错误的。我认为我应该将范围视为 [-pi, pi) 或类似的东西。在某些部分它计算正确,但有时它是错误的。有人可以帮助我使用这段代码或给我另一种旋转方法。

{

         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;
         }
}

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;
         }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

最单纯的乌龟 2024-10-18 15:46:29

一些可能有帮助的方法(角度始终以度为单位,而不是拉德):(

    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;
    }

您应该开始将有帮助的答案标记为答案,单击左侧投票下方的复选标记轮廓,例如您可以接受 这个答案

编辑:稍微优化了方法。

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.

予囚 2024-10-18 15:46:29

绕轨道运行的粒子位置可以用一行代码分别设置:

假设 p1、p2 和 p1、p2 p3 是 Vector2s 和 p2 & p3 绕着 p1 运行。

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

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

Matrix.Create...() 方法将为您调用两个三角函数。

编辑。矩阵与Vector2 结构和方法是 XNA 特定的,但包含在这里,因为这是 OP 标记他的 Q 的方法。

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.

爱冒险 2024-10-18 15:46:29
angle = Math.Acos(Vector2.Dot(heading,new Vector2(0,-1)));

正如您所怀疑的,点积和 Acos 的组合只会给您 180 度的角度
度范围。

相反,在单位向量上使用 Atan2 可以获得从 -pi 到 pi 的完整角度范围。

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

如果 Y 轴向下为正值,则可能需要对 Y 项取反。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文