一个漂亮的Delphi程序(Delphi在分形艺术中的应用)

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TBranchColor=record
  r,g,b:Byte;
  end;

  TFormMain = class(TForm)
    procedure FormResize(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    FGenPointFrom:TPoint;
    FGenLength:Real;
    FGenAngle:Real;
    FBranchWidth:Integer;
    FBranchColor:TBranchColor;
    Procedure SetParamters();
    Procedure DrawFractalTree(GenPointFrom:TPoint;GenLength,GenAngle:Real;BranchWidth:Integer;
                              BranchColor:TBranchColor);
  public
    { Public declarations }
    Procedure DrawTrunk();
    Procedure DrawBranch();
  end;

var
  FormMain: TFormMain;

const
  PI = 3.1416;
  PI2 = 2 * PI;
  GEN_ANGLE_DEVIATION = PI2 / 16;
  BRANCH_RATIO = 0.80;
  PROBABILITY_THREASHOLD = 0.10;

implementation

{$R *.dfm}

procedure TFormMain.FormResize(Sender: TObject);
begin
     Self.Invalidate;
end;

procedure TFormMain.FormPaint(Sender: TObject);
begin
     System.Randomize();
     Self.SetParamters();
     Self.DrawTrunk();
     Self.DrawBranch();
end;

procedure TFormMain.DrawBranch;
begin
     DrawFractalTree(FGenPointFrom,FGenLength*BRANCH_RATIO*BRANCH_RATIO,FGenAngle,FBranchWidth,FBranchColor);
end;

procedure TFormMain.DrawFractalTree(GenPointFrom: TPoint; GenLength,
  GenAngle: Real; BranchWidth: Integer; BranchColor: TBranchColor);
 function CanTerminate(GenPoint: TPoint; GenLength:Real): Boolean;
  begin
    if (GenPoint.X < 0) or (GenPoint.X > Self.ClientWidth)
      or (GenPoint.Y < 0) or (GenPoint.Y > Self.ClientHeight)
      or (GenLength < 1) then
      Result := True
    else
      Result := False;
  end;

  function ToPoint(GenPointFrom: TPoint; GenLength, GenAngle: Real; IsLeft: Boolean): TPoint;
  begin
    if IsLeft then
    begin
      Result.X := GenPointFrom.X + Trunc(GenLength * cos(GenAngle - GEN_ANGLE_DEVIATION));
      Result.Y := GenPointFrom.Y + Trunc(GenLength * sin(GenAngle - GEN_ANGLE_DEVIATION));
    end
    else
    begin
      Result.X := GenPointFrom.X + Trunc(GenLength * cos(GenAngle + GEN_ANGLE_DEVIATION));
      Result.Y := GenPointFrom.Y + Trunc(GenLength * sin(GenAngle + GEN_ANGLE_DEVIATION));
    end;
  end;

var
  GenPointTo: TPoint;
begin
  if CanTerminate(GenPointFrom, GenLength) then
  begin // 中断绘制
    System.Exit;
  end
  else
  begin // 绘制左右树干
    Application.ProcessMessages();
    if BranchWidth > 2 then Dec(BranchWidth, 2) else BranchWidth := 1;
    if BranchColor.g < 222 then Inc(BranchColor.g, 8) else BranchColor.g := 229;
    if System.Random > PROBABILITY_THREASHOLD then
    begin  // 绘制左树干
      GenPointTo := ToPoint(GenPointFrom, GenLength, GenAngle, True);
      Self.Canvas.Pen.Width := BranchWidth;
      Self.Canvas.Pen.Color := RGB(BranchColor.r, BranchColor.g, BranchColor.b);
      Self.Canvas.MoveTo(GenPointFrom.X, GenPointFrom.Y);
      Self.Canvas.LineTo(GenPointTo.X, GenPointTo.Y);
      DrawFractalTree(GenPointTo, GenLength*BRANCH_RATIO, GenAngle-GEN_ANGLE_DEVIATION, BranchWidth, BranchColor);
    end;
    if System.Random > PROBABILITY_THREASHOLD then
    begin  // 绘制右树干
      GenPointTo := ToPoint(GenPointFrom, GenLength, GenAngle, False);
      Self.Canvas.Pen.Width := BranchWidth;
      Self.Canvas.Pen.Color := RGB(BranchColor.r, BranchColor.g, BranchColor.b);
      Self.Canvas.MoveTo(GenPointFrom.X, GenPointFrom.Y);
      Self.Canvas.LineTo(GenPointTo.X, GenPointTo.Y);
      DrawFractalTree(GenPointTo, GenLength*BRANCH_RATIO, GenAngle+GEN_ANGLE_DEVIATION, BranchWidth, BranchColor);
    end;
  end;
end;
procedure TFormMain.DrawTrunk;
var
    GenPointTo:TPoint;
begin
    GenPointTo.X:=FGenPointFrom.X;
    GenPointTo.Y:=FGenPointFrom.Y-Trunc(FGenLength);
    Self.Canvas.Pen.Width:=FBranchWidth;
    Self.Canvas.Pen.Color:=RGB(FBranchColor.r,FBranchColor.g,FBranchColor.b);
    Self.Canvas.MoveTo(FGenPointFrom.X,FGenPointFrom.Y);
    Self.Canvas.LineTo(GenPointTo.X,GenPointTo.Y);
    Self.FGenPointFrom:=GenPointTo;
end;

procedure TFormMain.SetParamters;
begin
    Self.FGenPointFrom.X := Self.ClientWidth div 2;
    Self.FGenPointFrom.Y := Self.ClientHeight;
    Self.FGenLength := Self.ClientHeight / 4;
    Self.FGenAngle := PI2 * 3 / 4;
    Self.FBranchWidth := 10;
    Self.FBranchColor.r := 50;
    Self.FBranchColor.g := 50;
    Self.FBranchColor.b := 50;
end;

procedure TFormMain.FormCreate(Sender: TObject);
begin
    self.Color:=clWindow;
end;

end.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
用递归的方法画分形 用递归的方法画分形   分形几何是数学领域里新兴的课题,如果将形的每个元素按某种规则进行变形,得到新的形,以此类推,进行若干次变形后得到的形就是分形形。Couch曲线是最典型的分形形:   将一条线段按照1进行变换,得到1,再将1的每条线段按1的折线变换得到2,以此类推,进行6次变换就得到6,如果进行无限次变换,就得到的是Couch曲线,Couch曲线的维数不是整数维,更多详情请见分形方面的书籍。   用分形形能画许多漂亮案而被广泛地应用,下面将几个简单的分形形的代码与形大家分享。 //Couch曲线的画法 void Couch(CDC *pDC,int x1,int y1,int x2,int y2,int n) { //pDC是画的设备上下文的指针 //x1,y1,x2,y2是起始的两点 //其参数n是递归的层数 int x3,y3,x4,y4,x5,y5; //以下是根据空间几何计算出来的坐标 x3=x1+(x2-x1)/3; y3=y1+(y2-y1)/3; x4=x1+(x2-x1)*2/3; y4=y1+(y2-y1)*2/3; x5=x3+(x4-x3)/2+int(sqrt(3)*(y4-y3)/2); y5=y3-int(sqrt(3)*(x4-x3)/2)+(y4-y3)/2; //递归最后一层,递归的出口 if(n==1) { pDC->MoveTo(x1,y1); pDC->LineTo(x3,y3); pDC->LineTo(x5,y5); pDC->LineTo(x4,y4); pDC->LineTo(x2,y2); } else { //递归画 Couch(pDC,x1,y1,x3,y3,n-1); Couch(pDC,x3,y3,x5,y5,n-1); Couch(pDC,x5,y5,x4,y4,n-1); Couch(pDC,x4,y4,x2,y2,n-1); } } //斯宾斯基篓垫的画法 void Floor(CDC *pDC,int x1, int y1,int x2,int y2,int x3,int y3,int n) { //pDC是画的设备上下文的指针 //x1,y1,x2,y2,x3,y3是起始的三角形的三点坐标 //其参数n是递归的层数 int x11,x22,x33,y11,y22,y33; //以下是根据空间几何计算出来的坐标 x11=(x2+x3)/2; y11=(y2+y3)/2; x22=(x1+x3)/2; y22=(y1+y3)/2; x33=(x1+x2)/2; y33=(y1+y2)/2; pDC->MoveTo(x11,y11); pDC->LineTo(x22,y22); pDC->MoveTo(x11,y11); pDC->LineTo(x33,y33); pDC->MoveTo(x22,y22); pDC->LineTo(x33,y33); //递归最后一层,递归的出口 if(n==1) { pDC->MoveTo(x11,y11); pDC->LineTo(x22,y22); pDC->LineTo(x33,y33); pDC->LineTo(x11,y11); } else { //递归画 Floor(pDC,x1,y1,x33,y33,x22,y22,n-1); Floor(pDC,x33,y33,x2,y2,x11,y11,n-1); Floor(pDC,x22,y22,x11,y11,x3,y3,n-1); } } //分形矩形的画法 void Rect(CDC *pDC,int x1,int y1,int x2,int y2,int n) { //pDC是画的设备上下文的指针 //x1,y1,x2,y2是起始矩形坐标 //其参数n是递归的层数 int x3,y3,x4,y4,x5,y5,x6,y6; //以下是根据空间几何计算出来的坐标 x3=x1+(x2-x1)/3; y3=y1+(y2-y1)/3; x4=x1+(x2-x1)*2/3; y4=y1+(y2-y1)*2/3; x5=x3+(y4-y3); y5=y3-(x4-x3); x6=x4-(y3-y4); y6=y4+(x3-x4); pDC->MoveTo(x1,y1); pDC->LineTo(x3,y3); pDC->MoveTo(x4,y4); pDC->LineTo(x2,y2); //递归最后一层,递归的出口 if(n==1) { pDC->MoveTo(x1,y1); pDC->LineTo(x3,y3); pDC->LineTo(x5,y5); pDC->LineTo(x6,y6); pDC->LineTo(x4,y4); } else { //递归画 Rect(pDC,x3,y3,x5,y5,n-1); Rect(pDC,x5,y5,x6,y6,n-1); Rect(pDC,x6,y6,x4,y4,n-1); } } //分形树的画法,其参数n是递归的层数 void Tree(CDC *pDC,int x1,int y1,int x2,int y2,int n) { //pDC是画的设备上下文的指针 //x1,y1,x2,y2是起始矩形坐标 //其参数n是递归的层数 int x3,y3,x4,y4,x5,y5; //以下是根据空间几何计算出来的坐标 x3=x1+(x2-x1)/3; y3=y1+(y2-y1)/3; x4=x3+int((x1-x3)*cos(5*pi/6))-int((y1-y3)*sin(5*pi/6)); y4=y3+int((x1-x3)*sin(5*pi/6))+int((y1-y3)*cos(5*pi/6)); x5=x3+int((x1-x3)*cos(5*pi/6))+int((y1-y3)*sin(5*pi/6)); y5=y3-int((x1-x3)*sin(5*pi/6))+int((y1-y3)*cos(5*pi/6)); pDC->MoveTo(x1,y1); pDC->LineTo(x2,y2); //递归最后一层,递归的出口 if(n==1) { pDC->MoveTo(x3,y3); pDC->LineTo(x4,y4); pDC->MoveTo(x3,y3); pDC->LineTo(x5,y5); } else { //递归画 Tree(pDC,x3,y3,x2,y2,n-1); Tree(pDC,x3,y3,x4,y4,n-1); Tree(pDC,x3,y3,x5,y5,n-1); } }   上述的代码及形附有Visual C++源代码,并在Windows XP和Visual C++6.0下调试成功。更多的分形形及形坐标空间几何的计算方法请与作者联系。 最新评论 [发表评论] [文章投稿] 查看所有评论 推荐给好友 打印 改成sqrt(3.0)就好了,vs的问题,参数多类型重载没自己识别出来 ( maxint 发表于 2008-9-4 21:27:00) skinfeature界面产品特点介绍 SkinFeature完全支持各种常用控件及窗口 。对话框,单文档界面,多文档界面的全部支持。 完全支持PNG、TGA、bmp 像格式。 支持皮肤(.rss)文件加密。保护美工像不被别人非法使用,进一步保护自身知识产权。 支持从msstyle wba 等主题文件自动转化为rss皮肤文件。 SkinFeature完全支持 VC,Delphi,C#,VB.Net,Visual Basic,C++ Bulider, PowerBuilder, Win32 SDK Supported WTL, ATL, 第三方厂商SDK, OUTLOOK 等等界面换肤。 支持各Windows平台 Windows 9X/NT/2000/2003/XP/Vista 完全支持ANSI UNICODE 文字码格式。 完全支持动态换肤(*.rss),支持不规则窗体,支持美工设计自定义界面生成方案。 完全多线程,自定义窗口类换肤支持。 内含15种专业皮肤(.rss)文件。 内含SkinDesigner 皮肤文件开发工具。 http://www.skinfeature.com ( skinfeature 发表于 2008-6-18 17:30:00) change sqrt(3) to sqrt(3.0) ( Eric_wang 发表于 2007-10-30 9:59:00) x5=x3+(x4-x3)/2+int(sqrt(3)*(y4-y3)/2); y5=y3-int(sqrt(3)*(x4-x3)/2)+(y4-y3)/2; 运行是错误的啊? 错误 1 error C2668: 'sqrt' : ambiguous call to overloaded function d:\wordplay\c++\范例\fractral递归方法画分形\stdafx.cpp 19 错误 2 fatal error C1903: unable to recover from previous error(s); stopping compilation d:\wordplay\c++\范例\fractral递归方法画分形\stdafx.cpp 19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值