unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
Spin, BGRABitmap, BGRABitmapTypes, Math;
type
{ TForm1 }
TForm1 = class(TForm)
btnRefresh: TButton;
CheckBox1: TCheckBox;
Label1: TLabel;
Label2: TLabel;
PaintBox1: TPaintBox;
Panel1: TPanel;
seiAcross: TSpinEdit;
sejDown: TSpinEdit;
procedure btnRefreshClick(Sender: TObject);
procedure PaintBox1Paint(Sender: TObject);
procedure SpinChange(Sender: TObject);
private
procedure DrawZigZagPath(across, down: Integer; bmp: TBGRABitmap);
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
procedure TForm1.DrawZigZagPath(across, down: Integer; bmp: TBGRABitmap);
var
points, rotated: array of TPointF;
x, y, stepCount, dx, dy: Integer;
gridX, gridY: Single;
i: Integer;
minX, maxX, minY, maxY, cx, cy: Single;
Alternatif: Boolean;
Temp: TPointF;
begin
bmp.Fill(BGRA(0, 0, 0));
//across := seiAcross.Value;
//down := sejDown.Value;
gridX := bmp.Width / (across + 2);
gridY := bmp.Height / (down + 2);
SetLength(points, 0);
x := 0; y := 0;
stepCount := 1;
SetLength(points, Length(points) + 1);
points[High(points)] := PointF((x + 1) * gridX, (y + 1) * gridY);
Inc(y);
SetLength(points, Length(points) + 1);
points[High(points)] := PointF((x + 1) * gridX, (y + 1) * gridY);
while True do
begin
if stepCount mod 2 = 1 then
begin
dx := stepCount;
dy := -stepCount;
end
else
begin
dx := -stepCount;
dy := stepCount;
end;
Inc(x, dx);
Inc(y, dy);
if (x < 0) or (x > across) or (y < 0) or (y > down) then Break;
SetLength(points, Length(points) + 1);
points[High(points)] := PointF((x + 1) * gridX, (y + 1) * gridY);
if stepCount mod 2 = 1 then
Inc(x)
else
Inc(y);
if (x < 0) or (x > across) or (y < 0) or (y > down) then Break;
SetLength(points, Length(points) + 1);
points[High(points)] := PointF((x + 1) * gridX, (y + 1) * gridY);
Inc(stepCount);
end;
// Rotate the path 180° about its center
if Length(points) > 0 then
begin
minX := points[0].X; maxX := minX;
minY := points[0].Y; maxY := minY;
for i := 1 to High(points) do
begin
if points[i].X < minX then minX := points[i].X else if points[i].X > maxX then maxX := points[i].X;
if points[i].Y < minY then minY := points[i].Y else if points[i].Y > maxY then maxY := points[i].Y;
end;
cx := (minX + maxX) / 2;
cy := (minY + maxY) / 2;
SetLength(rotated, Length(points));
for i := 0 to High(points) do
rotated[i] := PointF(2 * cx - points[i].X, 2 * cy - points[i].Y);
Alternatif := False;
if Odd(seiAcross.Value+1) and (sejDown.Value>seiAcross.Value) then
Alternatif := True;
if Odd(seiAcross.Value+1) and (sejDown.Value<seiAcross.Value) and Odd(sejDown.Value) then
Alternatif := True;
if Odd(seiAcross.Value) and odd(sejDown.Value) and (seiAcross.Value > sejDown.Value) then
Alternatif := True;
for i := 1 to High(rotated) do
begin
if rotated[i].X = rotated[i+1].X-100 then rotated[i].X := rotated[i+1].X;
if not(Alternatif) then Continue;
if i mod 4 = 2 then
begin
Temp := rotated[i];
rotated[i] := rotated[i-1];
rotated[i-1] := Temp;
end;
if i mod 4 = 3 then
begin
Temp := rotated[i];
rotated[i] := rotated[i+1];
rotated[i+1] := Temp;
end;
end;
end;
for i := 0 to High(points) - 1 do
bmp.DrawLineAntialias(points[i].X, points[i].Y, points[i + 1].X, points[i + 1].Y, BGRA(255, 255, 0), 2);
for i := 0 to High(rotated) - 2 do
bmp.DrawLineAntialias(rotated[i].X, rotated[i].Y, rotated[i + 1].X, rotated[i + 1].Y, BGRA(0, 255, 255), 2);
end;
procedure TForm1.btnRefreshClick(Sender: TObject);
begin
Paintbox1.Invalidate;
end;
procedure TForm1.PaintBox1Paint(Sender: TObject);
var
bmp: TBGRABitmap;
begin
bmp := TBGRABitmap.Create(PaintBox1.Width, PaintBox1.Height);
try
DrawZigZagPath(seiAcross.Value, sejDown.Value, bmp);
bmp.Draw(PaintBox1.Canvas, 0, 0, True);
finally
bmp.Free;
end;
end;
procedure TForm1.SpinChange(Sender: TObject);
begin
if CheckBox1.Checked then
PaintBox1.Invalidate;
end;
end.