Mar*_*ars 6 c# graphics drawing rotation winforms
一段时间以来,我一直在我的各种程序中使用以下函数围绕枢轴点旋转一系列点。
\n\nprivate 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\nforeach (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\nfor (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我怎样才能少量地重复旋转呢?我可以保存基点并在旋转发生变化时使用它们来更新当前点,但这是唯一的方法吗?
\nPoint
由于该方法生成的整数舍入,您的位置测量已关闭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
值会发生的情况:
归档时间: |
|
查看次数: |
2173 次 |
最近记录: |