7

在此处输入图像描述我正在尝试使用此代码通过旋转点来旋转矩形

  var
 dx,dy:real;
 rotp:Tpoint;
begin
  dx := (CenterPoint.Y * Sin(angle)) - (CenterPoint.X * Cos(angle)) + CenterPoint.X;
  dy := -(CenterPoint.X * Sin(angle)) - (CenterPoint.Y * Cos(angle)) + CenterPoint.Y;
  rotP.X := round((point.X * Cos(angle)) - (point.Y * Sin(angle)) + dx);
  rotP.Y := round((point.X * Sin(angle)) + (point.Y * Cos(angle)) + dy);
  result:= rotP;
end;

但是圆形功能使矩形变形,有谁知道如何克服这个问题?

我附上了图像,白点是我围绕中心点旋转的点,我确定图像旋转得很好,因此白点应该与图像的角相同。

4

3 回答 3

7

我能看到这种方法会失败的唯一方法是,如果你正在变换周长上的每个点。如果您正在这样做,请不要这样做。使用图形基元转换角并在每个角之间绘制线条。

更新:您的评论让游戏消失了。每次通过转换为整数进行数字化时,您都在重复旋转并累积错误。通过将坐标存储为双精度值来处理这个问题,并在需要绘制时按需转换为整数。

事实上,如果我是你,我会将你的主数据视为一个位置和一个角度,两者都存储为双精度。我根本不会存储角落的坐标。我会存储一个位置(中心或角落之一)和一个方向角(相对于固定的全局轴系统)。这样,您将始终绘制一个真正的矩形。在每个积分步骤根据需要增加位置和方向,然后根据主数据计算角的位置。这样做,您将永远不会受到形状扭曲的影响。

于 2011-11-20T13:59:16.253 回答
4

由于浮点变量的分辨率有限,浮点计算,尤其是三角函数,总是容易出错。当您将坐标差与三角函数相乘而不是乘以坐标并减去结果时,您可以提高计算的精度。您可以尝试此代码(假设角度为弧度并使用 math.pas):

var
  dx,dy,ca,sa:Extended;
  rotp:Tpoint;
begin
  SinCos(angle, sa, ca);
  dx := point.x - CenterPoint.X;
  dy := point.y - CenterPoint.Y;
  result.X := CenterPoint.X + round(dx*ca - dy*sa);
  result.Y := CenterPoint.Y + round(dx*sa + dy*ca);
end;

更新:根据大卫编辑的答案,你不应该使用增量旋转,因为这会增加舍入误差。

于 2011-11-20T14:23:58.973 回答
1
type
  TRectangle = record
    A, B, C, D: TPoint;
  end;

var
  Rectangle, // master rect
  TurnedRectangle: TRectangle; // turned rect

...

procedure RotateRectangle;
begin
  TurnedRectangle.A := RotatePoint(Rectangle.A);
  ...
  DrawRectangle
end

function RotatePoint(Point: TPoint): TPoint;
var
  dx, dy: Real;
  rotp: TPoint;
begin
  dx := (CenterPoint.Y * Sin(angle)) - (CenterPoint.X * Cos(angle)) + CenterPoint.X;
  dy := -(CenterPoint.X * Sin(angle)) - (CenterPoint.Y * Cos(angle)) + CenterPoint.Y;
  rotP.X := Round((Point.X * Cos(angle)) - (point.Y * Sin(angle)) + dx);
  rotP.Y := Round((Point.X * Sin(angle)) + (point.Y * Cos(angle)) + dy);
  result:= rotP;
end;

procedure DrawRectangle;
begin
  Canvas.Polygon([TurnedRectangle.A, TurnedRectangle.B, TurnedRectangle.C, TurnedRectangle.D]);
end;
于 2011-11-20T16:00:04.233 回答