旋转矩形点可单独扭曲矩形

时间:2011-11-20 13:40:06

标签: delphi rotation graphic

enter image description here我正在尝试使用此代码

旋转其点来旋转矩形
  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;

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

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

3 个答案:

答案 0 :(得分:7)

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

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

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

答案 1 :(得分: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;

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

答案 2 :(得分: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;