C# 围绕轴心点重复旋转点
一段时间以来,在我的各种程序中,我一直在使用以下函数围绕轴心点旋转一系列点C# 围绕轴心点重复旋转点,c#,rotation,drawing,point,C#,Rotation,Drawing,Point,一段时间以来,在我的各种程序中,我一直在使用以下函数围绕轴心点旋转一系列点 private Point RotatePoint(Point point, Point pivot, double radians) { var cosTheta = Math.Cos(radians); var sinTheta = Math.Sin(radians); var x = (cosTheta * (point.X - pivot.X) - sinTheta * (point.Y
private Point RotatePoint(Point point, Point 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 Point((int)x, (int)y);
}
这一直都很有效,直到我尝试以少量重复旋转一个形状。例如,这是我在一个由4个点组成的矩形多边形上称之为45°得到的结果:
foreach (var point in points)
Rotate(point, center, Math.PI / 180f * 45);
但这是我通过调用旋转45次得到的1°:
for (var i = 0; i < 45; ++i)
foreach (var point in points)
Rotate(point, center, Math.PI / 180f * 1)
for(变量i=0;i<45;++i)
foreach(变量点到点)
旋转(点、中心、Math.PI/180f*1)
只要我只叫它一次就好了,而且旋转度越低,情况似乎也会越来越糟。该函数是否存在一些缺陷,或者我是否误解了该函数的基本功能
我怎么能以少量重复旋转?我可以保存基点,并在旋转发生变化时使用它们更新当前点,但这是唯一的方法吗?如果需要,可以使用Media3D仅处理矩阵并简化编码。像这样简单的事情就行了
public Point3D Rotate(Point3D point, Point3D rotationCenter, Vector3D rotation, double degree)
{
// create empty matrix
var matrix = new Matrix3D();
// translate matrix to rotation point
matrix.Translate(rotationCenter - new Point3D());
// rotate it the way we need
matrix.Rotate(new Quaternion(rotation, degree));
// apply the matrix to our point
point = matrix.Transform(point);
return point;
}
然后您只需调用该方法并指定旋转。假设您使用2D(如示例中所示),并假设我们使用XY平面,因此旋转在Z方向。您可以执行以下操作:
var rotationPoint = new Point3D(0, 0, 0);
var currentPoint = new Point3D(10, 0, 0);
// rotate the current point around the rotation point in Z by 45 degree
var newPoint = Rotate(currentPoint, rotation, new Vector3D(0, 0, 1), 45d);
正如TaW正确指出的,由于
RotatePoint()
方法生成的整数舍入,您的点
位置度量值已关闭。使用
float
坐标对方法返回值进行简单更正,将生成正确的度量值:要对其进行测试,请创建一个计时器,并将其
勾号事件注册为RotateTimerTick()
:
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)));
}
这是使用float
值得出的结果:
这就是使用integer
值时发生的情况:
你能换成F点吗?谢谢你的回答,在这里查看答案之前,我刚刚意识到了这一点。这么愚蠢的小错误。