围绕枢轴点重复旋转点

Mar*_*ars 6 c# graphics drawing rotation winforms

一段时间以来,我一直在我的各种程序中使用以下函数围绕枢轴点旋转一系列点。

\n\n
private Point RotatePoint(Point point, Point pivot, double radians)\n{\n    var cosTheta = Math.Cos(radians);\n    var sinTheta = Math.Sin(radians);\n\n    var x = (cosTheta * (point.X - pivot.X) - sinTheta * (point.Y - pivot.Y) + pivot.X);\n    var y = (sinTheta * (point.X - pivot.X) + cosTheta * (point.Y - pivot.Y) + pivot.Y);\n\n    return new Point((int)x, (int)y);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这一直很有效,直到我尝试反复少量旋转形状。例如,这是我在由 4 个点组成的矩形多边形上调用 45\xc2\xb0 得到的结果:

\n\n
foreach (var point in points)\n    Rotate(point, center, Math.PI / 180f * 45);\n
Run Code Online (Sandbox Code Playgroud)\n\n

在此输入图像描述

\n\n

但这是我通过对 1\xc2\xb0 调用旋转 45 次得到的结果:

\n\n
for (var i = 0; i < 45; ++i)\n    foreach (var point in points)\n        Rotate(point, center, Math.PI / 180f * 1)\n
Run Code Online (Sandbox Code Playgroud)\n\n

在此输入图像描述

\n\n

只要调用一次就可以了,而且似乎旋转度越低,情况就逐渐变差。该函数是否存在一些缺陷,或者我是否误解了该函数的一些基本功能?

\n\n

我怎样才能少量地重复旋转呢?我可以保存基点并在旋转发生变化时使用它们来更新当前点,但这是唯一的方法吗?

\n

Jim*_*imi 4

Point由于该方法生成的整数舍入,您的位置测量已关闭RotatePoint()

使用坐标对方法返回值进行简单修正float,将产生正确的测量值:

要测试它,请创建一个计时器并将其Tick事件注册为RotateTimerTick()

添加了旋转增量(请参见“rotationSpin场”)以强调运动效果。

PointF pivotPoint = new PointF(100F, 100F);
PointF rotatingPoint = new PointF(50F, 100F);
double rotationSpin = 0D;

private PointF RotatePoint(PointF point, PointF pivot, double radians)
{
    var cosTheta = Math.Cos(radians);
    var sinTheta = Math.Sin(radians);

    var x = (cosTheta * (point.X - pivot.X) - sinTheta * (point.Y - pivot.Y) + pivot.X);
    var y = (sinTheta * (point.X - pivot.X) + cosTheta * (point.Y - pivot.Y) + pivot.Y);

    return new PointF((float)x, (float)y);
}

private void RotateTimerTick(object sender, EventArgs e)
{
    rotationSpin += .5;
    
    if (rotationSpin > 90) rotationSpin = 0;
    rotatingPoint = RotatePoint(rotatingPoint, pivotPoint, (Math.PI / 180f) * rotationSpin);
    Panel1.Invalidate(new Rectangle(new Point(50,50), new Size(110, 110)));
}

private void Panel1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    e.Graphics.FillEllipse(Brushes.White, new RectangleF(100, 100, 8, 8));
    e.Graphics.FillEllipse(Brushes.Yellow, new RectangleF(rotatingPoint, new SizeF(8, 8)));
}
Run Code Online (Sandbox Code Playgroud)

这是使用值的结果float

在此输入图像描述

这就是使用integer值会发生的情况:

在此输入图像描述