Показать сообщение отдельно
  #5  
Старый 17.04.2017, 21:58
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,015
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Цитата:
Сообщение от NumLock
SetWorldTransform. Примеров по вращению навалом в интернете.

Походу, нафих не нужно. Если вращение идет вокруг базовой окружности, то достаточно просто посчитать угол и ПЕРЕРИСОВАТЬ картинку.

Примерно так:
Код:
unit Unit1;

interface

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

type
  TShapeType = (stArc, stSector);

  TCircleShape = class
  private
    fShapeType : TShapeType; // Type of the shape - arc or sector
    fX0, fY0 : Integer; // Center of the circle
    fR : Integer; // Radius of the circle
    fAA : Integer; // Angle of sector/arc
    fAR : Integer; // Angle of rotation, by default = 0
  public
    constructor Create(X0,Y0,R : Integer; ArcAngle : Integer; ShapeType : TShapeType = stArc);

    function ToRadian(Angle : Integer) : Double;

    procedure PaintTo(ACanvas : TCanvas); // draw on provided canvas
    procedure Rotate(Angle : Integer); // Rotate to the angle

    property ShapeType : TShapeType read fShapeType write fShapeType;
  end;

  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    Button1: TButton;
    Button2: TButton;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure PaintBox1Paint(Sender: TObject);
    procedure RadioButton1Click(Sender: TObject);
  private
    { Private declarations }
    FShape : TCircleShape;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{TCircleShape}

constructor TCircleShape.Create(X0,Y0,R : Integer; ArcAngle : Integer; ShapeType : TShapeType = stArc);
begin
  fX0 := X0;
  fY0 := Y0;
  fR := R;
  fAA := ArcAngle;
  fShapeType := ShapeType;

  fAR := 0;
end;

function TCircleShape.ToRadian(Angle : Integer) : Double;
begin
  Result := (Angle * 2 * PI) / 360;
end;

procedure TCircleShape.PaintTo(ACanvas : TCanvas); // draw on provided canvas
var
  X1, Y1 : Integer;
  X2, Y2 : Integer;
begin
  X1 := fX0 + Round(fR*Cos(fAR*2*PI/340));
  Y1 := fY0 - Round(fR*Sin(fAR*2*PI/340));
  X2 := fX0 + Round(fR*Cos((fAR-fAA)*2*PI/340));
  Y2 := fY0 - Round(fR*Sin((fAR-fAA)*2*PI/340));

  ACanvas.Arc(fX0-fR,fY0-fR,fX0+fR,fY0+fR,X2,Y2,X1,Y1);

  If fShapeType = stSector Then
    Begin
      ACanvas.MoveTo(fX0,fY0);
      ACanvas.LineTo(X1,Y1);
      ACanvas.MoveTo(fX0,fY0);
      ACanvas.LineTo(X2,Y2);
    End;
end;

procedure TCircleShape.Rotate(Angle : Integer); // Rotate to the angle
begin
  fAR := fAR + Angle;
end;

{TForm1}

procedure TForm1.Button1Click(Sender: TObject);
begin
  FShape.Rotate(5);
  PaintBox1.Repaint;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  FShape.Rotate(-5);
  PaintBox1.Repaint;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FShape := TCircleShape.Create(100,100,50,20);
  PaintBox1.Repaint;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeAndNil(FShape);
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  PaintBox1.Canvas.FillRect(Rect(0,0,PaintBox1.Width,PaintBox1.Height));
  FShape.PaintTo(PaintBox1.Canvas);
end;

procedure TForm1.RadioButton1Click(Sender: TObject);
begin
  If RadioButton1.Checked
    Then FShape.ShapeType := stArc
    Else FShape.ShapeType := stSector;
  PaintBox1.Repaint;
end;

end.

Проект в аттаче.
В принципе, класс можно переместить в отдельный модуль. Он никак не связан с формой, только тогда в форме указать uses этого модуля.
Вложения
Тип файла: zip example.ZIP (51.4 Кбайт, 10 просмотров)
Ответить с цитированием