unit RotShp;
interface
uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs,
ExtCtrls;
type
TRotateShape = class(TShape)
private
FAngle: Integer;
FShapeWidth: Integer;
FShapeHeight: Integer;
procedure SetAngle(Value: Integer);
procedure SetShapeHeight(const Value: Integer);
procedure SetShapeWidth(const Value: Integer);
protected
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
published
property ShapeWidth: Integer read FShapeWidth write SetShapeWidth;
property ShapeHeight: Integer read FShapeHeight write SetShapeHeight;
property Angle: Integer read FAngle write SetAngle;
end;
procedure Register;
implementation
uses
Math;
procedure Register;
begin
RegisterComponents('Samples', [TRotateShape]);
end;
{ TRotateShape }
const
MinDist = 30;
type
TDblPoint = record
x, y: Extended;
end;
function DblPoint(x, y: Extended): TDblPoint;
begin
Result.x := x;
Result.y := y;
end;
constructor TRotateShape.Create(AOwner: TComponent);
begin
inherited;
FShapeWidth := Width;
FShapeHeight := Height;
FAngle := 0;
end;
procedure TRotateShape.Paint;
var
p: array of TPoint;
fp: array of TDblPoint;
Cnt, i: Integer;
Len, Alpha, Pho, Theta, a, b, x, y: Extended;
begin
x := Width * 0.5;
y := Height * 0.5;
a := FShapeWidth * 0.5;
b := FShapeHeight * 0.5;
if Shape in [stSquare, stRoundSquare, stCircle] then
if a < b then b := a
else a := b;
case Shape of
stRectangle, stSquare:
begin
SetLength(fp, 4);
fp[0] := DblPoint(-a, -b);
fp[1] := DblPoint( a, -b);
fp[2] := DblPoint( a, b);
fp[3] := DblPoint(-a, b);
end;
stRoundRect, stRoundSquare:
if (FShapeWidth <= 25) or (FShapeHeight <= 25) then begin
SetLength(fp, 4);
fp[0] := DblPoint(-a, -b);
fp[1] := DblPoint( a, -b);
fp[2] := DblPoint( a, b);
fp[3] := DblPoint(-a, b);
end else begin
SetLength(fp, 16);
fp[0] := DblPoint(-a + 5, -b);
fp[1] := DblPoint(a - 5, -b);
fp[2] := DblPoint(a - 5 + Cos(DegToRad(300)) * 5,
-b + 5 + Sin(DegToRad(300)) * 5);
fp[3] := DblPoint(a - 5 + Cos(DegToRad(330)) * 5,
-b + 5 + Sin(DegToRad(330)) * 5);
fp[4] := DblPoint(a, -b + 5);
fp[5] := DblPoint(a, b - 5);
fp[6] := DblPoint(a - 5 + Cos(DegToRad(30)) * 5,
b - 5 + Sin(DegToRad(30)) * 5);
fp[7] := DblPoint(a - 5 + Cos(DegToRad(60)) * 5,
b - 5 + Sin(DegToRad(60)) * 5);
fp[8] := DblPoint(a - 5, b);
fp[9] := DblPoint(-a + 5, b);
fp[10] := DblPoint(-a + 5 + Cos(DegToRad(120)) * 5,
b - 5 + Sin(DegToRad(120)) * 5);
fp[11] := DblPoint(-a + 5 + Cos(DegToRad(150)) * 5,
b - 5 + Sin(DegToRad(150)) * 5);
fp[12] := DblPoint(-a, b - 5);
fp[13] := DblPoint(-a, -b + 5);
fp[14] := DblPoint(-a + 5 + Cos(DegToRad(210)) * 5,
-b + 5 + Sin(DegToRad(210)) * 5);
fp[15] := DblPoint(-a + 5 + Cos(DegToRad(240)) * 5,
-b + 5 + Sin(DegToRad(240)) * 5);
end;
stEllipse, stCircle:
begin
Len := Pi * a * b;
Cnt := Round(Len / MinDist);
SetLength(fp, Cnt);
for i := 0 to Cnt - 1 do begin
Alpha := i * 2 * Pi / Cnt;
fp := DblPoint(a * Cos(Alpha), b * Sin(Alpha));
end;
end;
end;
SetLength(p, Length(fp));
Alpha := DegToRad(FAngle);
for i := Low(fp) to High(fp) do begin
Pho := Sqrt(Sqr(fp.x) + Sqr(fp.y));
Theta := ArcTan2(fp.y, fp.x) + Alpha;
p := Point(Round(x + Pho * Cos(Theta)), Round(y + Pho * Sin(Theta)));
end;
Canvas.Pen := Pen;
Canvas.Brush := Brush;
Canvas.Polygon(p);
end;
procedure TRotateShape.SetAngle(Value: Integer);
begin
Value := Value mod 360;
if FAngle <> Value then begin
FAngle := Value;
Invalidate;
end;
end;
procedure TRotateShape.SetShapeHeight(const Value: Integer);
begin
if FShapeHeight <> Value then begin
FShapeHeight := Value;
Invalidate;
end;
end;
procedure TRotateShape.SetShapeWidth(const Value: Integer);
begin
if FShapeWidth <> Value then begin
FShapeWidth := Value;
Invalidate;
end;
end;
end.