Фрактальное дерево
Генерация фрактального дерева с помощью рекурсивной функции. Сама генерация происходит при построении случайным образом листьев и веток дерева. Для этого создаётся процедура Tree(x, y: Integer; a: Real; l: Integer). На первом шаге эта процедура получает координаты начала дерева ((x, y: Integer), угол наклона ствола (a: Real) и длину основной ветви (l: Integer). Во время работы процедуры проверяется длина вновь сгенерированной линии, при этом,если она слишком коротка, то мы будем считать её листом, а не веткой. Координаты конца ветки вычисляются учитывая переданный угол "a": x1 := Round(x + l*cos(a)); y1 := Round(y + l*sin(a)); Далее на основании длинны ветки, мы вводим дополнительную переменную и ее обработку для сохранения некоторых веток длинными. Те ветви, что будут признаны короткими следующим условием if p < 40 будут дополнительно обрисованы листвой. При рисовании листвы мы случайно выбираем цвет из двух близких для листвы и циклом for i:=0 to 3 , где 3 - это ширина основания листа, отрисовываем лист на основании ранее вычисленных координат paintbox1.Canvas.Line(x+i,y,x1,y1) Если же длина ветви оказалась большой, мы рисуем ветку вместо листа в цикле for i := 0 to (p div 6).Здесь толщина ветки зависит от её длины. Далее в цикле for i := 0 to 9 - Random(9) создаётся случайное число веток или листьев из одного узла (от 0 до 9), вычисляется коэфициент длины будущих веток s := Random(l - l div 6) + (l div 6) и угол наклона будущих побегов a1 := a + 1.6 * (0.5 - Random).На основании s и a1 вычисляются длины будущих побегов: x1 := Round(x + s * cos(a)); y1 := Round(y + s * sin(a)); Далее следует рекурсивный вызов процедуры Tree для прорисовки новых листьев и веток согласно полученному случайному количеству.Припередаче данных в процедуру Tree изменяется случайным образом длина веток. Чем меньше будет число отнимаемое от длины ветки, тем больше будет ветвление: Tree(x1, y1, a1, p - 5 - Random(30))
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
PaintBox1: TPaintBox;
procedure Button1Click(Sender: TObject);
procedure Tree(x, y: Integer; a: Real; l: Integer);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
kount:integer;
implementation
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
Tree(320, 580, 3*pi/2, 200);
end;
procedure TForm1.Tree(x, y: Integer; a: Real; l: Integer);
var
x1, y1: Integer;
p, s : Integer;
i : Integer;
a1 : Real;
begin
if l < 8 then
exit;
x1 := Round(x + l*cos(a));
y1 := Round(y + l*sin(a));
if l > 100 then
p := 100
else
p := l;
if p < 40 then
begin
//Генерация листьев
if Random > 0.5 then
paintbox1.Canvas.Pen.Color:=clgreen
else
paintbox1.Canvas.Pen.Color:=rgbtocolor(90,139,5);
for i := 0 to 3 do
paintbox1.Canvas.Line(x+i,y,x1,y1);
end
else
begin
//Генерация веток
paintbox1.Canvas.Pen.Color:=rgbtocolor(100,3,4);
for i := 0 to (p div 6) do
paintbox1.Canvas.Line(x + i - (p div 12), y, x1, y1);
end;
//Следующие ветки
for i := 0 to 9 - Random(9) do
begin
s := Random(l - l div 6) + (l div 6);
a1 := a + 1.6 * (0.5 - Random); //Угол наклона веток
x1 := Round(x + s * cos(a));
y1 := Round(y + s * sin(a));
Tree(x1, y1, a1, p - 5 - Random(30)); //Чем меньше вычетаем, тем пышнее дерево
end;
end;
initialization
{$I unit1.lrs}
end.
Материал позаимствован с сайта
|