问题描述
我将对铁路信号进行可视化显示。问题是我只是不能绘制平行四边形形状,所以我只是从另一个程序中导入了它。问题是:我真的不知道如何将平行四边形向右旋转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