【问题标题】:Rotate a point around another point围绕另一个点旋转一个点
【发布时间】:2012-11-21 15:08:45
【问题描述】:

我的任务是绘制一个特定的图形。作为这项任务的一部分,我需要将一些点旋转 45 度。

我已经花了 2 天时间试图计算一个公式,但就是无法正确计算。 我一直在到处搜索,包括这个特定的网站,我已经非常接近了,但我仍然不在那里。

这里是: 我需要画4个不同的点

我有一个特定的公式来计算那里的位置,这超出了问题的范围,但这是我得到的结果:

int radius = 576;
int diameter = radius * 2;
Point blueA = new Point(561, 273);
Point greenB = new Point(273, 561);
Point yellowC = new Point (849, 561);
Point redD = new Point (561, 849);

现在我需要将这些点旋转 45 度。我使用下面的代码来实现它:

double rotationAngle = 45;
double rotationRadians = rotationAngle * (Math.PI / 180);
int center = radius;    
result.X = (int)(Math.Cos(rotationRadians) * ((double)result.X - (double)center) - (double)Math.Sin(rotationRadians) * ((double)result.Y - center) + (double)center);
result.Y = (int)(Math.Sin(rotationRadians) * ((double)result.X - (double)center) + (double)Math.Cos(rotationRadians) * ((double)result.Y - center) + (double)center);

但这就是我得到的:

任何帮助将不胜感激

【问题讨论】:

    标签: c# rotation gdi trigonometry


    【解决方案1】:

    问题是int center = radius,您正在设置int radius = 576。这没有任何意义,因为您肯定正在围绕应该具有 x 和 y 位置的点旋转。

    假设您围绕原点旋转,中心 xy 都应该是 0 而不是 576

    所以,既然如此,试试这个。

    /// <summary>
    /// Rotates one point around another
    /// </summary>
    /// <param name="pointToRotate">The point to rotate.</param>
    /// <param name="centerPoint">The center point of rotation.</param>
    /// <param name="angleInDegrees">The rotation angle in degrees.</param>
    /// <returns>Rotated point</returns>
    static Point RotatePoint(Point pointToRotate, Point centerPoint, double angleInDegrees)
    {
        double angleInRadians = angleInDegrees * (Math.PI / 180);
        double cosTheta = Math.Cos(angleInRadians);
        double sinTheta = Math.Sin(angleInRadians);
        return new Point
        {
            X =
                (int)
                (cosTheta * (pointToRotate.X - centerPoint.X) -
                sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X),
            Y =
                (int)
                (sinTheta * (pointToRotate.X - centerPoint.X) +
                cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y)
        };
    }
    

    这样使用。

    Point center = new Point(0, 0); 
    Point newPoint = RotatePoint(blueA, center, 45);
    

    显然,如果中心点始终为0,0,那么您可以相应地简化函数,或者通过默认参数或重载方法使中心点成为可选。您可能还希望将一些可重用的数学封装到其他静态方法中。

    例如

    /// <summary>
    /// Converts an angle in decimal degress to radians.
    /// </summary>
    /// <param name="angleInDegrees">The angle in degrees to convert.</param>
    /// <returns>Angle in radians</returns>
    static double DegreesToRadians(double angleInDegrees)
    {
       return angleInDegrees * (Math.PI / 180);
    }
    
    /// <summary>
    /// Rotates a point around the origin
    /// </summary>
    /// <param name="pointToRotate">The point to rotate.</param>
    /// <param name="angleInDegrees">The rotation angle in degrees.</param>
    /// <returns>Rotated point</returns>
    static Point RotatePoint(Point pointToRotate, double angleInDegrees)
    {
       return RotatePoint(pointToRotate, new Point(0, 0), angleInDegrees);
    }
    

    这样使用。

    Point newPoint = RotatePoint(blueA, 45);
    

    最后,如果您使用 GDI,您也可以简单地执行RotateTransform。 见:http://msdn.microsoft.com/en-us/library/a0z3f662.aspx

    Graphics g = this.CreateGraphics();
    g.TranslateTransform(blueA);
    g.RotateTransform(45);
    

    【讨论】:

    • 完美!谢谢你。这是当前截图:s8.postimage.org/e7r44klcl/result.png
    • 你是对的。操作系统库的贡献者必须手动复制它,因为括号被搞砸了,并且在单元测试中出现了错误。
    • 有人可以指出一个资源来理解RotatePoint中的方程式吗?
    • @BryceGuinta 这只是基本的触发 - mathsisfun.com/algebra/trigonometry-index.html
    • 我使用这个公式通过求解 theta 并将方程的左手设置为我想要的值来计算将某物旋转到固定位置所需的角度。对于x=0,此公式为Math.Atan2(pointToRotate.Y - centerPoint.Y, centerPoint.X - pointToRotate.Y)。请注意,常规 atan 并不适用于所有象限,因此需要 Atan2。
    【解决方案2】:

    我觉得你的数学很奇怪。我认为 dx = r*Cos(theta) 和 dy = r*Sin(theta)。

    这是我写的一个小程序,因为这让我很困扰,而且我已经好几年没做数学了。

    Point center = new Point() { X = 576, Y = 576 };
    
    Point previous = new Point() { X = 849, Y=561 };
    double rotation = 45;
    double rotationRadians = rotation * (Math.PI / 180);
    
    //get radius based on the previous point and r squared = a squared + b squared
    double r = Math.Sqrt(Math.Pow(previous.X - center.X, 2) + Math.Pow(previous.Y - center.Y, 2));
    Console.WriteLine("r = " + r.ToString());
    
    //calculate previous angle
    double previousAngle = Math.Atan((previous.Y - center.Y) / (previous.X - center.X));
    Console.WriteLine("Previous angle: " + previousAngle.ToString());
    
    double newAngle = previousAngle + rotationRadians;
    
    Point newP = new Point();
    newP.X = center.X + r * Math.Cos(newAngle);
    newP.Y = center.Y + r * Math.Sin(newAngle);
    
    Console.WriteLine("(" + newP.X.ToString() + ", " + newP.Y.ToString() + ")");
    
    Console.ReadLine();
    

    【讨论】:

    • 我在代码的不同部分使用该方法,在某个阶段,我得到了带有这些坐标的“前一个”点:X = 576 Y = 20。在这种情况下,我得到了“DivideByZeroException " 如果我​​将 "try -> catch" 块放入,结果如下:s10.postimage.org/azjdc7rex/exception.png
    猜你喜欢
    • 2014-12-26
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    相关资源
    最近更新 更多