如何旋转导入的图片?

问题描述

enter image description here

我将对铁路信号进行可视化显示。问题是我只是不能绘制平行四边形形状,所以我只是从另一个程序中导入了它。问题是:我真的不知道如何将平行四边形向右旋转45度。有什么想法吗?

解决方法

无需加载图片:您可以​​使用“画布”绘制功能绘制方阵图:

procedure TForm1.FormPaint(Sender: TObject);
var
    Points : array of TPoint;
begin
    SetLength(Points,4);
    Points[0] := Point(10,20);
    Points[1] := Point(30,20);
    Points[2] := Point(40,30);
    Points[3] := Point(20,30);
    // Border of polygon
    Canvas.Pen.Width   := 2;
    Canvas.Pen.Color   := clYellow;
    // Interior color of polygon
    Canvas.Brush.Color := clRed;
    Canvas.Polygon(Points);
end;

您还可以使用GDI +进行绘制,该图形允许进行诸如旋转,平移,翻转等更多的变换。

这是一个代码示例:

uses Winapi.GDIPAPI,Winapi.GDIPOBJ,Winapi.GDIPUTIL;

procedure TForm1.FormPaint(Sender: TObject);
var
    Graphics  : TGPGraphics;
    GdiPen    : TGPPen;
    GdiBrush  : TGPBrush;
    GdiPoints : array of TGPPoint;
    GdiMatrix : TGPMatrix;
begin
    Graphics  := TGPGraphics.Create(Canvas.Handle);
    GdiPen    := TGPPen.Create(GPColor(clYellow),4);
    GdiBrush  := TGPSolidBrush.Create(GPColor(clRed));
    GdiMatrix := TGPMatrix.Create();

    SetLength(GdiPoints,4);
    GdiPoints[0] := MakePoint(110,20);
    GdiPoints[1] := MakePoint(150,20);
    GdiPoints[2] := MakePoint(190,80);
    GdiPoints[3] := MakePoint(150,80);

    Graphics.FillPolygon(GdiBrush,PGPPoint(@GdiPoints[0]),Length(GdiPoints));
    Graphics.DrawPolygon(GdiPen,Length(GdiPoints));

    GdiMatrix.RotateAt(30.0,MakePoint(110.0,30.0));
    Graphics.SetTransform(GdiMatrix);
    GdiPen.SetWidth(1);
    GdiPen.SetColor(GPColor(clBlack));
    // This line is horizontal but it will be rotate by the transformation set
    Graphics.DrawLine(GdiPen,110,30,190,30);

    FreeAndNil(GdiMatrix);
    FreeAndNil(GdiPen);
    FreeAndNil(GdiBrush);
    FreeAndNil(Graphics);
end;

您可以使用TGPMatrixMultiply组合多个转换。例如:您创建了类似于上面代码的矩阵,但是使用了Translate方法,然后如上所述创建了旋转矩阵,并在调用SetTransform之前使用了乘法将两者合并。请注意,这不是可交换的!先翻译然后旋转的效果与先旋转然后翻译的效果不同。

,

使用矢量图形绘制几何/无定形(填充)形状。只需从TPalallelogramm创建一个实例即可绘制任意大小/移动/旋转的Palallelogramm。它存储计算出的坐标,直到其数据之一改变为止。因此重绘变得更快。

演示PAS:

unit Unit3;

interface

uses
  Winapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.Dialogs,Vcl.StdCtrls;

type
  TPoint2D = packed record
    case b : byte of
      0: ( x,y : double );
      1: ( coords : array [0..1] of double );
  end;

  TPalallelogramm = class
    private
      // Fields
      fLocation : TPoint2D;
      fSideSizes : TPoint2D;
      fAngle : double;
      fRotationAngle : double;
      fLineColor : cardinal;
      fFillColor : cardinal;

      // Derived fields
      fValidPoints : boolean;
      fPoints : array [0..3] of TPoint;

    protected
      // Virtual methods
      procedure validatePoints; virtual;
      function isValueChanged( const valueOld_,valueNew_ : double ) : boolean; virtual;

    public
      procedure setLocationCoordAt( ndx_ : byte; const coord_ : double );
      procedure setSideSizeAt( ndx_ : byte; const size_ : double );
      procedure setAngle( const angle_ : double );
      procedure setRotationAngle( const rotationAngle_ : double );
      procedure setLineColor( lineColor_ : cardinal );
      procedure setFillColor( fillColor_ : cardinal );
      procedure drawToCanvas( canvas_ : TCanvas );

  end;

  TForm3 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    fPalallelogramm : TPalallelogramm;

  public
    { Public declarations }
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

const
  CONST_distance_Minimum : double = 1e-5;

procedure TPalallelogramm.validatePoints;
var
  sideA,sideB : TPoint2D;

  procedure setPointAt( ndx_ : byte; const x_,y_ : double );
  var
    ppt : PPoint;
  begin
    ppt := @fPoints[ndx_];
    ppt^.x := round( fLocation.x + x_ );
    ppt^.y := round( fLocation.y + y_ );
  end;

  function rotatePoint( const x_,y_,angle_ : double ) : TPoint2D;
  var
    s,c : double;
  begin
    s := sin( angle_ );
    c := cos( angle_ );
    result.x := x_*c - y_*s;
    result.y := y_*c - x_*s;
  end;

begin
  sideA := rotatePoint( fSideSizes.x,fRotationAngle );
  sideB := rotatePoint( fSideSizes.y,fAngle + fRotationAngle );

  setPointAt( 0,0 );
  setPointAt( 1,sideA.x,sideA.y );
  setPointAt( 2,sideA.x + sideB.x,sideA.y + sideB.y );
  setPointAt( 3,sideB.x,sideB.y );
  fValidPoints := TRUE;
end;

function TPalallelogramm.isValueChanged( const valueOld_,valueNew_ : double ) : boolean;
begin
  result := abs( valueNew_ - valueOld_ ) > CONST_distance_Minimum;
end;

procedure TPalallelogramm.setLocationCoordAt( ndx_ : byte; const coord_ : double );
begin
  if ( ndx_ < 2 ) then
  begin
    if ( isValueChanged( fLocation.coords[ndx_],coord_ ) ) then
    begin
      fLocation.coords[ndx_] := coord_;
      fValidPoints := FALSE;
    end;
  end else
    ;//raise...
end;

procedure TPalallelogramm.setSideSizeAt( ndx_ : byte; const size_ : double );
begin
  if ( ndx_ < 2 ) then
  begin
    if ( isValueChanged( fSideSizes.coords[ndx_],size_ ) ) then
    begin
      fSideSizes.coords[ndx_] := size_;
      fValidPoints := FALSE;
    end;
  end else
    ;//raise...
end;

procedure TPalallelogramm.setAngle( const angle_ : double );
begin
  if ( isValueChanged( fAngle,angle_ ) ) then
  begin
    fAngle := angle_;
    fValidPoints := FALSE;
  end;
end;

procedure TPalallelogramm.setRotationAngle( const rotationAngle_ : double );
begin
  if ( isValueChanged( fRotationAngle,rotationAngle_ ) ) then
  begin
    fRotationAngle := rotationAngle_;
    fValidPoints := FALSE;
  end;
end;

procedure TPalallelogramm.setLineColor( lineColor_ : cardinal );
begin
  fLineColor := lineColor_;
end;

procedure TPalallelogramm.setFillColor( fillColor_ : cardinal );
begin
  fFillColor := fillColor_;
end;

procedure TPalallelogramm.drawToCanvas( canvas_ : TCanvas );
begin
  if ( canvas_ <> NIL ) then
  begin
    if ( not fValidPoints ) then
      validatePoints;
    canvas_.pen.style := psSolid;
    canvas_.pen.width := 1;
    canvas_.pen.color := fLineColor;

    canvas_.brush.style := bsSolid;
    canvas_.brush.color := fFillColor;

    canvas_.Polygon( fPoints );
  end else
    ;//raise...
end;


procedure TForm3.Button1Click(Sender: TObject);
begin
  fPalallelogramm.drawToCanvas( canvas );
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
  fPalallelogramm := TPalallelogramm.Create;
  fPalallelogramm.setLocationCoordAt( 0,500 );
  fPalallelogramm.setLocationCoordAt( 1,500 );
  fPalallelogramm.setSideSizeAt( 0,100 );
  fPalallelogramm.setSideSizeAt( 1,50 );
  fPalallelogramm.setAngle( pi/3 );
  fPalallelogramm.setRotationAngle( pi/9 );
  fPalallelogramm.setLineColor( clBlue );
  fPalallelogramm.setFillColor( clYellow );
end;

procedure TForm3.FormDestroy(Sender: TObject);
begin
  fPalallelogramm.Free;
end;

end.

演示DFM:

object Form3: TForm3
  Left = 0
  Top = 0
  Caption = 'Form3'
  ClientHeight = 411
  ClientWidth = 852
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 8
    Top = 368
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
end