随笔 - 2146  文章 - 19 评论 - 11846 阅读 - 1267万


矩阵旋转一个角度, 会关联到 M11、M12、M21、M22 四个数据, 计算公式如下:
┏                  ┓
┃ cos(r)  sin(r)  0┃
┃-sin(r)  cos(r)  0┃
┃ DX      DY      1┃
┗                  ┛

//其中的 r 不是角度是弧度; 弧度的计算方法是: r = 角度 * Pi / 180.


下面两段程序对上面的公式进行了对比测试:

//
var
  m: IGPMatrix;
begin
  m := TGPMatrix.Create;
  m.Rotate(90);
  ShowMessageFmt('%f  %f', [m.Elements.M11, m.Elements.M12]); // 0.00  1.00
  ShowMessageFmt('%f  %f', [m.Elements.M21, m.Elements.M22]); //-1.00  0.00

  m.Reset;
  m.Rotate(-30);
  ShowMessageFmt('%f  %f', [m.Elements.M11, m.Elements.M12]); //0.87  -0.50
  ShowMessageFmt('%f  %f', [m.Elements.M21, m.Elements.M22]); //0.50   0.87
end;

//
var
  r: Single;
  M11,M12,M21,M22: Single;
begin
  r := 90 * Pi/180;
  M11 := Cos(r);  M12 := Sin(r);
  M21 := -Sin(r); M22 := Cos(r);
  ShowMessageFmt('%f  %f', [M11, M12]); // 0.00  1.00
  ShowMessageFmt('%f  %f', [M21, M22]); //-1.00  0.00

  r := -30 * Pi/180;
  M11 := Cos(r);  M12 := Sin(r);
  M21 := -Sin(r); M22 := Cos(r);
  ShowMessageFmt('%f  %f', [M11, M12]); //0.87  -0.50
  ShowMessageFmt('%f  %f', [M21, M22]); //0.50   0.87
end;


观察一个点的旋转效果(从蓝色旋转 90 度到红色):



uses GdiPlus;

procedure TForm1.FormPaint(Sender: TObject);
var
  Graphics: IGPGraphics;
  Pen: IGPPen;
  Brush: IGPSolidBrush;
  Matrix: IGPMatrix;
  i: Integer;
  Pt: TGPPointF;
begin
  ClientWidth := 300;
  ClientHeight := 200;
  
  Pen := TGPPen.Create($FFE0E0E0);
  Brush := TGPSolidBrush.Create($FF0000FF);
  Graphics := TGPGraphics.Create(Handle);

  //绘制坐标系
  Graphics.Clear($FFFFFFFF);
  for i := 1 to ClientWidth div 10 do
    Graphics.DrawLine(Pen, TGPPoint.Create(i*10, 0), TGPPoint.Create(i*10, ClientHeight));
  for i := 1 to ClientHeight div 10 do
    Graphics.DrawLine(Pen, TGPPoint.Create(0, i*10), TGPPoint.Create(ClientWidth, i*10));

  Pen.Color := $FFB0B0B0;
  Graphics.DrawLine(Pen, TGPPoint.Create(ClientWidth div 2, 0), 
                         TGPPoint.Create(ClientWidth div 2, ClientHeight));
  Graphics.DrawLine(Pen, TGPPoint.Create(0, ClientHeight div 2), 
                         TGPPoint.Create(ClientWidth, ClientHeight div 2));

  //平移坐标系
  Graphics.TranslateTransform(ClientWidth div 2, ClientHeight div 2);
  Graphics.PixelOffsetMode := PixelOffsetModeHalf;
  Graphics.DrawEllipse(Pen, -2, -2, 5, 5);

  //假如有个点是 (80, -40), 用蓝色绘制此点
  Pt.Initialize(80, -40);
  Graphics.DrawLine(Pen, TGPPointF.Create(0, 0), Pt);
  Graphics.FillRectangle(Brush, Pt.X-2, Pt.Y-2, 5, 5);

  //旋转 90 度, 用红色重新绘制这个点
  Graphics.RotateTransform(90);
  Graphics.PixelOffsetMode := PixelOffsetModeHalf;
  Brush.Color := $FFFF0000;
  Graphics.DrawLine(Pen, TGPPointF.Create(0, 0), Pt);
  Graphics.FillRectangle(Brush, Pt.X-2, Pt.Y-2, 5, 5);
end;


旋转变换 IGPMatrix.Rotate() 或 IGPGraphics.RotateTransform 都有绕着 (0,0) 点的;

IGPMatrix.RotateAt() 可绕指定点旋转, 如:



uses GdiPlus;

procedure TForm1.FormPaint(Sender: TObject);
var
  Graphics: IGPGraphics;
  Matrix: IGPMatrix;
  Pen: IGPPen;
  Rect: TGPRect;
begin
  Graphics := TGPGraphics.Create(Handle);
  Pen := TGPPen.Create($FFD0D0D0, 2);
  Rect.Initialize(50, 30, 80, 80);

  Graphics.Clear($FFFFFFFF);
  Graphics.DrawRectangle(Pen, Rect);

  Matrix := TGPMatrix.Create;
  Matrix.RotateAt(45, TGPPointF.Create(Rect.X + Rect.Width/2, Rect.Y + Rect.Height/2));
  Graphics.MultiplyTransform(Matrix);

  Pen.Color := $80FF0000;
  Graphics.DrawRectangle(Pen, Rect);
end;

posted on   万一  阅读(3401)  评论(3编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
历史上的今天:
2008-12-25 看看盛大的小伙子们
2007-12-25 颜色表


点击右上角即可分享
微信分享提示