uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Math;
type
TDrawType = (dtMaxRadius, dtMaxAngle);
type
TformMain = class(TForm)
btnDraw1: TButton;
btnDraw2: TButton;
rbArchimedes: TRadioButton;
rbFermat: TRadioButton;
rbGalilei: TRadioButton;
rbPoinsot: TRadioButton;
editCoeff: TEdit;
procedure btnDraw1Click(Sender: TObject);
procedure btnDraw2Click(Sender: TObject);
procedure rbArchimedesClick(Sender: TObject);
procedure rbFermatClick(Sender: TObject);
procedure rbGalileiClick(Sender: TObject);
procedure rbPoinsotClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
HowToDraw: TDrawType;
end;
function RoArchimedes(A, Theta: Extended): Extended;
function RoFermat(A, Theta: Extended): Extended;
function RoGalilei(A, Theta: Extended): Extended;
function RoPoinsot(A, Theta: Extended): Extended;
var
formMain: TformMain;
Ro: function (A, Theta: Extended): Extended;
implementation
function RoArchimedes(A, Theta: Extended): Extended;
begin
Result := A * Theta;
end;
function RoFermat(A, Theta: Extended): Extended;
begin
Result := A * Power(Theta, 1/2);
end;
function RoGalilei(A, Theta: Extended): Extended;
begin
Result := A * (1 - sqr(Theta));
end;
function RoPoinsot(A, Theta: Extended): Extended;
begin
Result := A * SecH(Theta/3);
end;
procedure TformMain.btnDraw1Click(Sender: TObject);
var
i, x, y, cx, cy, MaxR, MaxT: Integer;
a, theta, R: Double;
begin
Canvas.Brush.Color := clBtnFace;
Canvas.FillRect(ClientRect);
try
StringReplace(editCoeff.Text, '.', DecimalSeparator, [rfReplaceAll]);
StringReplace(editCoeff.Text, ',', DecimalSeparator, [rfReplaceAll]);
a := StrToFloat(editCoeff.Text);
except
on E: EConvertError do
begin
MessageDlg('Cannot convert coefficient A to number!',
mtError, [mbOK], 0);
Exit;
end;
end;
cx := ClientWidth div 2;
cy := ClientHeight div 2;
MaxR := 200;
MaxT := 1000;
i := 0;
repeat
theta := i * 0.001 * (2 * pi);
R := Ro(a, theta);
case HowToDraw of
dtMaxRadius: if abs(R) > MaxR then Break;
dtMaxAngle: if abs(Theta) > MaxT then Break;
end;
x := cx - Round(R * Cos(theta));
y := cy + Round(R * Sin(theta));
Canvas.Pixels[x,y] := clRed;
Inc(i);
until False;
end;
procedure TformMain.btnDraw2Click(Sender: TObject);
var
Centre: TPoint;
SpiralWidth, SpiralHeight: Integer;
var
x, y: Integer;
angle, max_angle: Extended;
a, r2, delta: Extended;
ARect: TRect;
begin
Centre := Point(ClientWidth div 2, ClientHeight div 2);
SpiralWidth := 400; SpiralHeight := 300;
ARect := Rect(Centre.x - SpiralWidth div 2, Centre.y - SpiralHeight div 2,
Centre.x + SpiralWidth div 2, Centre.y + SpiralHeight div 2);
Canvas.DrawFocusRect(ARect);
Canvas.Brush.Color := clBtnFace;
Canvas.FillRect(ClientRect);
try
StringReplace(editCoeff.Text, '.', DecimalSeparator, [rfReplaceAll]);
StringReplace(editCoeff.Text, ',', DecimalSeparator, [rfReplaceAll]);
a := StrToFloat(editCoeff.Text);
except
on E: EConvertError do
begin
MessageDlg('Cannot convert coefficient A to number!',
mtError, [mbOK], 0);
Exit;
end;
end;
delta := 0.7;
// большой при равном A и возрастающем радиусе.
max_angle := (sqr(SpiralWidth div 2) + sqr(SpiralWidth div 2)) / 100;
for y := ARect.Top to ARect.Bottom do
for x := ARect.Left to ARect.Right do
begin
angle := ArcTan2(Centre.y - y, x - Centre.x);
if (angle < 0) then angle := angle + 2 * pi;
r2 := sqr(x - Centre.x) + sqr(Centre.y - y);
while (angle <= max_angle) do
begin
if (abs(abs(Ro(a, angle)) - sqrt(r2)) < delta) then
Canvas.Pixels[x,y] := clBlack;
angle := angle + 2 * pi;
end;
end;
end;
procedure TformMain.rbArchimedesClick(Sender: TObject);
begin
Ro := RoArchimedes;
editCoeff.Text := '15';
HowToDraw := dtMaxRadius;
end;
procedure TformMain.rbFermatClick(Sender: TObject);
begin
Ro := RoFermat;
editCoeff.Text := '35';
HowToDraw := dtMaxRadius;
end;
procedure TformMain.rbGalileiClick(Sender: TObject);
begin
Ro := RoGalilei;
editCoeff.Text := '1';
HowToDraw := dtMaxRadius;
end;
procedure TformMain.rbPoinsotClick(Sender: TObject);
begin
Ro := RoPoinsot;
editCoeff.Text := '200';
HowToDraw := dtMaxAngle;
end;
procedure TformMain.FormCreate(Sender: TObject);
begin
rbArchimedesClick(Self);
end;
В центре плохо прорисовывается спираль - это ущербность перевода в полярные координаты. Чем больше вожусь с этим, тем лучше мне кажется верный и простой способ MBo.
Всё, дальше сам.