Fractal tree

You are encouraged to solve this task according to the task description, using any language you may know.
Generate and draw a fractal tree.
To draw a fractal tree is simple:
- Draw the trunk
- At the end of the trunk, split by some angle and draw two branches
- Repeat at the end of each branch until a sufficient level of branching is reached
- Cf.
AutoHotkey
Image - Link, since uploads seem to be disabled currently.
<lang AutoHotkey>#SingleInstance, Force
- NoEnv
SetBatchLines, -1
- Uncomment if Gdip.ahk is not in your standard library
- #Include, Gdip.ahk
FileOut := A_Desktop "\MyNewFile.png" TreeColor := 0xff0066ff ; ARGB TrunkWidth := 10 ; Pixels TrunkLength := 80 ; Pixels Angle := 60 ; Degrees ImageWidth := 670 ; Pixels ImageHeight := 450 ; Pixels Branches := 13 Decrease := 0.81
Angle := (Angle * 0.01745329252) / 2 , Points := {} , Points[1, "Angle"] := 0 , Points[1, "X"] := ImageWidth // 2 , Points[1, "Y"] := ImageHeight - TrunkLength
if (!pToken := Gdip_Startup()) { MsgBox, 48, Gdiplus error!, Gdiplus failed to start. Please ensure you have Gdiplus on your system. ExitApp } OnExit, Exit
pBitmap := Gdip_CreateBitmap(ImageWidth, ImageHeight) , G := Gdip_GraphicsFromImage(pBitmap) , Gdip_SetSmoothingMode(G, 4) , pBrush := Gdip_BrushCreateSolid(0xff000000) , Gdip_FillRectangle(G, pBrush, -5, -5, ImageWidth + 10, ImageHeight + 10) , Gdip_DeleteBrush(pBrush) , pPen := Gdip_CreatePen(TreeColor, TrunkWidth/Decrease) , Gdip_DrawLine(G, pPen, Points.1.X, Points.1.Y, Points.1.X, ImageHeight) , Gdip_DeletePen(pPen)
Loop, % Branches { NewPoints := {} pPen := Gdip_CreatePen(TreeColor, TrunkWidth) for Each, Point in Points { N1 := A_Index * 2 , N2 := (A_Index * 2) + 1 , NewPoints[N1, "X"] := Point.X + (TrunkLength * Sin(NewPoints[N1, "Angle"] := Point.Angle - Angle)) , NewPoints[N1, "Y"] := Point.Y - (TrunkLength * Cos(NewPoints[N1].Angle)) , NewPoints[N2, "X"] := Point.X + (TrunkLength * Sin(NewPoints[N2, "Angle"] := Point.Angle + Angle)) , NewPoints[N2, "Y"] := Point.Y - (TrunkLength * Cos(NewPoints[N2].Angle)) , Gdip_DrawLine(G, pPen, Point.X, Point.Y, NewPoints[N1].X, NewPoints[N1].Y) , Gdip_DrawLine(G, pPen, Point.X, Point.Y, NewPoints[N2].X, NewPoints[N2].Y) } TrunkWidth *= Decrease , TrunkLength *= Decrease , Points := NewPoints , Gdip_DeletePen(pPen) }
Gdip_SaveBitmapToFile(pBitmap, FileOut) , Gdip_DisposeImage(pBitmap) , Gdip_DeleteGraphics(G) Run, % FileOut
Exit: Gdip_Shutdown(pToken) ExitApp</lang>
BASIC256

<lang basic256>graphsize 300,300
level = 12 : len =63 # initial values x = 230: y = 285 rotation = pi/2
A1 = pi/27 : A2 = pi/8 # constants which determine shape C1 = 0.7 : C2 = 0.85
dim xs(level+1) : dim ys(level+1) # stacks
fastgraphics color black rect 0,0,graphwidth,graphheight refresh color green gosub tree refresh imgsave "Fractal_tree_BASIC-256.png", "PNG" end
tree: xs[level] = x : ys[level] = y gosub putline if level>0 then level = level - 1 len = len*C1 rotation = rotation - A1 gosub tree len = len/C1*C2 rotation = rotation + A1 + A2 gosub tree rotation = rotation - A2 len = len/C2 level = level + 1 end if x = xs[level] : y = ys[level] return
putline: yn = -sin(rotation)*len + y xn = cos(rotation)*len + x line x,y,xn,yn x = xn : y = yn return</lang>
BBC BASIC
- Output:

<lang bbcbasic>
Spread = 25 Scale = 0.76 SizeX% = 400 SizeY% = 300 Depth% = 10
</lang><lang bbcbasic>
VDU 23,22,SizeX%;SizeY%;8,16,16,128 PROCbranch(SizeX%, 0, SizeY%/2, 90, Depth%) END
DEF PROCbranch(x1, y1, size, angle, depth%) LOCAL x2, y2 x2 = x1 + size * COSRAD(angle) y2 = y1 + size * SINRAD(angle) VDU 23,23,depth%;0;0;0; LINE x1, y1, x2, y2 IF depth% > 0 THEN PROCbranch(x2, y2, size * Scale, angle - Spread, depth% - 1) PROCbranch(x2, y2, size * Scale, angle + Spread, depth% - 1) ENDIF ENDPROC</lang>
C
or
<lang c>#include <SDL/SDL.h>
- ifdef WITH_CAIRO
- include <cairo.h>
- else
- include <SDL/sge.h>
- endif
- include <cairo.h>
- include <stdlib.h>
- include <time.h>
- include <math.h>
- ifdef WITH_CAIRO
- define PI 3.1415926535
- endif
- define SIZE 800 // determines size of window
- define SCALE 5 // determines how quickly branches shrink (higher value means faster shrinking)
- define BRANCHES 14 // number of branches
- define ROTATION_SCALE 0.75 // determines how slowly the angle between branches shrinks (higher value means slower shrinking)
- define INITIAL_LENGTH 50 // length of first branch
double rand_fl(){
return (double)rand() / (double)RAND_MAX;
}
void draw_tree(SDL_Surface * surface, double offsetx, double offsety,
double directionx, double directiony, double size, double rotation, int depth) {
- ifdef WITH_CAIRO
cairo_surface_t *surf = cairo_image_surface_create_for_data( surface->pixels, CAIRO_FORMAT_RGB24,
surface->w, surface->h, surface->pitch );
cairo_t *ct = cairo_create(surf);
cairo_set_line_width(ct, 1); cairo_set_source_rgba(ct, 0,0,0,1); cairo_move_to(ct, (int)offsetx, (int)offsety); cairo_line_to(ct, (int)(offsetx + directionx * size), (int)(offsety + directiony * size)); cairo_stroke(ct);
- else
sge_AALine(surface, (int)offsetx, (int)offsety, (int)(offsetx + directionx * size), (int)(offsety + directiony * size), SDL_MapRGB(surface->format, 0, 0, 0));
- endif
if (depth > 0){ // draw left branch draw_tree(surface, offsetx + directionx * size, offsety + directiony * size, directionx * cos(rotation) + directiony * sin(rotation), directionx * -sin(rotation) + directiony * cos(rotation), size * rand_fl() / SCALE + size * (SCALE - 1) / SCALE, rotation * ROTATION_SCALE, depth - 1); // draw right branch draw_tree(surface, offsetx + directionx * size, offsety + directiony * size, directionx * cos(-rotation) + directiony * sin(-rotation), directionx * -sin(-rotation) + directiony * cos(-rotation), size * rand_fl() / SCALE + size * (SCALE - 1) / SCALE, rotation * ROTATION_SCALE, depth - 1); }
}
void render(SDL_Surface * surface){
SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 255, 255, 255)); draw_tree(surface, surface->w / 2.0, surface->h - 10.0, 0.0, -1.0, INITIAL_LENGTH, PI / 8, BRANCHES); SDL_UpdateRect(surface, 0, 0, 0, 0);
}
int main(){
SDL_Surface * screen; SDL_Event evt; SDL_Init(SDL_INIT_VIDEO); srand((unsigned)time(NULL)); screen = SDL_SetVideoMode(SIZE, SIZE, 32, SDL_HWSURFACE); render(screen); while(1){ if (SDL_PollEvent(&evt)){ if(evt.type == SDL_QUIT) break; } SDL_Delay(1); } SDL_Quit(); return 0;
}</lang>
C++
- include <windows.h>
- include <string>
- include <math.h>
//-------------------------------------------------------------------------------------------------- using namespace std;
//-------------------------------------------------------------------------------------------------- const float PI = 3.1415926536f;
//-------------------------------------------------------------------------------------------------- class myBitmap { public:
myBitmap() : pen( NULL ) {} ~myBitmap() {
DeleteObject( pen ); DeleteDC( hdc ); DeleteObject( bmp );
}
bool create( int w, int h ) {
BITMAPINFO bi; void *pBits; ZeroMemory( &bi, sizeof( bi ) ); bi.bmiHeader.biSize = sizeof( bi.bmiHeader ); bi.bmiHeader.biBitCount = sizeof( DWORD ) * 8; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biWidth = w; bi.bmiHeader.biHeight = -h;
HDC dc = GetDC( GetConsoleWindow() ); bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 ); if( !bmp ) return false;
hdc = CreateCompatibleDC( dc ); SelectObject( hdc, bmp ); ReleaseDC( GetConsoleWindow(), dc );
width = w; height = h;
return true;
}
void setPenColor( DWORD clr ) {
if( pen ) DeleteObject( pen ); pen = CreatePen( PS_SOLID, 1, clr ); SelectObject( hdc, pen );
}
void saveBitmap( string path ) {
BITMAPFILEHEADER fileheader; BITMAPINFO infoheader; BITMAP bitmap; DWORD* dwpBits; DWORD wb; HANDLE file;
GetObject( bmp, sizeof( bitmap ), &bitmap );
dwpBits = new DWORD[bitmap.bmWidth * bitmap.bmHeight]; ZeroMemory( dwpBits, bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ) ); ZeroMemory( &infoheader, sizeof( BITMAPINFO ) ); ZeroMemory( &fileheader, sizeof( BITMAPFILEHEADER ) );
infoheader.bmiHeader.biBitCount = sizeof( DWORD ) * 8; infoheader.bmiHeader.biCompression = BI_RGB; infoheader.bmiHeader.biPlanes = 1; infoheader.bmiHeader.biSize = sizeof( infoheader.bmiHeader ); infoheader.bmiHeader.biHeight = bitmap.bmHeight; infoheader.bmiHeader.biWidth = bitmap.bmWidth; infoheader.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD );
fileheader.bfType = 0x4D42; fileheader.bfOffBits = sizeof( infoheader.bmiHeader ) + sizeof( BITMAPFILEHEADER ); fileheader.bfSize = fileheader.bfOffBits + infoheader.bmiHeader.biSizeImage;
GetDIBits( hdc, bmp, 0, height, ( LPVOID )dwpBits, &infoheader, DIB_RGB_COLORS );
file = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); WriteFile( file, &fileheader, sizeof( BITMAPFILEHEADER ), &wb, NULL ); WriteFile( file, &infoheader.bmiHeader, sizeof( infoheader.bmiHeader ), &wb, NULL ); WriteFile( file, dwpBits, bitmap.bmWidth * bitmap.bmHeight * 4, &wb, NULL ); CloseHandle( file );
delete [] dwpBits;
}
HDC getDC() { return hdc; } int getWidth() { return width; } int getHeight() { return height; }
private:
HBITMAP bmp; HDC hdc; HPEN pen; int width, height;
}; //-------------------------------------------------------------------------------------------------- class vector2 { public:
vector2() { x = y = 0; } vector2( int a, int b ) { x = a; y = b; } void set( int a, int b ) { x = a; y = b; } void rotate( float angle_r ) {
float _x = static_cast<float>( x ), _y = static_cast<float>( y ), s = sinf( angle_r ), c = cosf( angle_r ), a = _x * c - _y * s, b = _x * s + _y * c;
x = static_cast<int>( a ); y = static_cast<int>( b );
}
int x, y;
}; //-------------------------------------------------------------------------------------------------- class fractalTree { public:
fractalTree() { _ang = DegToRadian( 24.0f ); } float DegToRadian( float degree ) { return degree * ( PI / 180.0f ); }
void create( myBitmap* bmp ) {
_bmp = bmp; float line_len = 130.0f;
vector2 sp( _bmp->getWidth() / 2, _bmp->getHeight() - 1 ); MoveToEx( _bmp->getDC(), sp.x, sp.y, NULL ); sp.y -= static_cast<int>( line_len ); LineTo( _bmp->getDC(), sp.x, sp.y);
drawRL( &sp, line_len, 0, true ); drawRL( &sp, line_len, 0, false );
}
private:
void drawRL( vector2* sp, float line_len, float a, bool rg ) {
line_len *= .75f; if( line_len < 2.0f ) return;
MoveToEx( _bmp->getDC(), sp->x, sp->y, NULL ); vector2 r( 0, static_cast<int>( line_len ) );
if( rg ) a -= _ang; else a += _ang;
r.rotate( a ); r.x += sp->x; r.y = sp->y - r.y;
LineTo( _bmp->getDC(), r.x, r.y );
drawRL( &r, line_len, a, true ); drawRL( &r, line_len, a, false );
}
myBitmap* _bmp; float _ang;
}; //-------------------------------------------------------------------------------------------------- int main( int argc, char* argv[] ) {
ShowWindow( GetConsoleWindow(), SW_MAXIMIZE );
myBitmap bmp; bmp.create( 640, 512 ); bmp.setPenColor( RGB( 255, 255, 0 ) );
fractalTree tree; tree.create( &bmp );
BitBlt( GetDC( GetConsoleWindow() ), 0, 20, 648, 512, bmp.getDC(), 0, 0, SRCCOPY );
bmp.saveBitmap( "f://rc//fracTree.bmp" );
system( "pause" );
return 0;
} //-------------------------------------------------------------------------------------------------- </lang>
Clojure
<lang Clojure>(import '[java.awt Color Graphics] 'javax.swing.JFrame)
(defn deg-to-radian [deg] (* deg Math/PI 1/180)) (defn cos-deg [angle] (Math/cos (deg-to-radian angle))) (defn sin-deg [angle] (Math/sin (deg-to-radian angle)))
(defn draw-tree [^Graphics g, x y angle depth]
(when (pos? depth) (let [x2 (+ x (int (* depth 10 (cos-deg angle))))
y2 (+ y (int (* depth 10 (sin-deg angle))))]
(.drawLine g x y x2 y2) (draw-tree g x2 y2 (- angle 20) (dec depth)) (recur g x2 y2 (+ angle 20) (dec depth)))))
(defn fractal-tree [depth]
(doto (proxy [JFrame] []
(paint [g] (.setColor g Color/BLACK) (draw-tree g 400 500 -90 depth)))
(.setBounds 100 100 800 600) (.setResizable false) (.setDefaultCloseOperation JFrame/DISPOSE_ON_CLOSE) (.show)))
(fractal-tree 9)</lang>
Common Lisp
<lang lisp>;; (require :lispbuilder-sdl)
(defun deg-to-radian (deg)
"converts degrees to radians" (* deg pi 1/180))
(defun cos-deg (angle)
"returns cosin of the angle expressed in degress" (cos (deg-to-radian angle)))
(defun sin-deg (angle)
"returns sin of the angle expressed in degress" (sin (deg-to-radian angle)))
(defun draw-tree (surface x y angle depth)
"draws a branch of the tree on the sdl-surface" (when (plusp depth) (let ((x2 (+ x (round (* depth 10 (cos-deg angle)))))
(y2 (+ y (round (* depth 10 (sin-deg angle))))))
(sdl:draw-line-* x y x2 y2 :surface surface :color sdl:*green*) (draw-tree surface x2 y2 (- angle 20) (1- depth)) (draw-tree surface x2 y2 (+ angle 20) (1- depth)))))
(defun fractal-tree (depth)
"shows a window with a fractal tree" (sdl:with-init () (sdl:window 800 600 :title-caption "fractal-tree") (sdl:clear-display sdl:*black*) (draw-tree sdl:*default-surface* 400 500 -90 depth) (sdl:update-display) (sdl:with-events () (:video-expose-event ()
(sdl:update-display))
(:quit-event ()
t))))
(fractal-tree 9) </lang>
D
SVG Version
<lang d>import std.stdio, std.math;
enum width = 1000, height = 1000; // Image dimension. enum length = 400; // Trunk size. enum scale = 6.0 / 10; // Branch scale relative to trunk.
void tree(in double x, in double y, in double length, in double angle) {
if (length < 1) return; immutable x2 = x + length * angle.cos; immutable y2 = y + length * angle.sin; writefln("<line x1='%f' y1='%f' x2='%f' y2='%f' " ~ "style='stroke:black;stroke-width:1'/>", x, y, x2, y2); tree(x2, y2, length * scale, angle + PI / 5); tree(x2, y2, length * scale, angle - PI / 5);
}
void main() {
"<svg width='100%' height='100%' version='1.1' xmlns='http://www.w3.org/2000/svg'>".writeln; tree(width / 2.0, height, length, 3 * PI / 2); "</svg>".writeln;
}</lang>
Turtle Version
This uses the turtle module from the Dragon Curve task, and the module from the Grayscale Image task.
<lang d>import grayscale_image, turtle;
void tree(Color)(Image!Color img, ref Turtle t, in uint depth,
in real step, in real scale, in real angle) { if (depth == 0) return; t.forward(img, step); t.right(angle); img.tree(t, depth - 1, step * scale, scale, angle); t.left(2 * angle); img.tree(t, depth - 1, step * scale, scale, angle); t.right(angle); t.forward(img, -step);
}
void main() {
auto img = new Image!Gray(330, 300); auto t = Turtle(165, 270, -90); img.tree(t, 10, 80, 0.7, 30); img.savePGM("fractal_tree.pgm");
}</lang>
Alternative version
Using DFL. <lang d>import dfl.all; import std.math;
class FractalTree: Form {
private immutable DEG_TO_RAD = PI / 180.0;
this() { width = 600; height = 500; text = "Fractal Tree"; backColor = Color(0xFF, 0xFF, 0xFF); startPosition = FormStartPosition.CENTER_SCREEN; formBorderStyle = FormBorderStyle.FIXED_DIALOG; maximizeBox = false; }
private void drawTree(Graphics g, Pen p, int x1, int y1, double angle, int depth) { if (depth == 0) return; int x2 = x1 + cast(int) (cos(angle * DEG_TO_RAD) * depth * 10.0); int y2 = y1 + cast(int) (sin(angle * DEG_TO_RAD) * depth * 10.0); g.drawLine(p, x1, y1, x2, y2); drawTree(g, p, x2, y2, angle - 20, depth - 1); drawTree(g, p, x2, y2, angle + 20, depth - 1); } protected override void onPaint(PaintEventArgs ea){ super.onPaint(ea); Pen p = new Pen(Color(0, 0xAA, 0)); drawTree(ea.graphics, p, 300, 450, -90, 9); }
}
int main() {
int result = 0; try { Application.run(new FractalTree); } catch(Exception e) { msgBox(e.msg, "Fatal Error", MsgBoxButtons.OK, MsgBoxIcon.ERROR); result = 1; } return result;
}</lang>
F#
<lang fsharp>let (cos, sin, pi) = System.Math.Cos, System.Math.Sin, System.Math.PI
let (width, height) = 1000., 1000. // image dimension let scale = 6./10. // branch scale relative to trunk let length = 400. // trunk size
let rec tree x y length angle =
if length >= 1. then let (x2, y2) = x + length * (cos angle), y + length * (sin angle) printfn "<line x1='%f' y1='%f' x2='%f' y2='%f' style='stroke:rgb(0,0,0);stroke-width:1'/>" x y x2 y2 tree x2 y2 (length*scale) (angle + pi/5.) tree x2 y2 (length*scale) (angle - pi/5.)
printfn "<?xml version='1.0' encoding='utf-8' standalone='no'?> <!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> <svg width='100%%' height='100%%' version='1.1' xmlns='http://www.w3.org/2000/svg'>" tree (width/2.) height length (3.*pi/2.) printfn "</svg>"</lang>
Fantom
<lang fantom> using fwt using gfx
class FractalCanvas : Canvas {
new make () : super() {}
Void drawTree (Graphics g, Int x1, Int y1, Int angle, Int depth) { if (depth == 0) return Int x2 := x1 + (angle.toFloat.toRadians.cos * depth * 10.0).toInt; Int y2 := y1 + (angle.toFloat.toRadians.sin * depth * 10.0).toInt; g.drawLine(x1, y1, x2, y2); drawTree(g, x2, y2, angle - 20, depth - 1); drawTree(g, x2, y2, angle + 20, depth - 1); }
override Void onPaint (Graphics g) { drawTree (g, 400, 500, -90, 9) }
}
class FractalTree {
public static Void main () { Window { title = "Fractal Tree" size = Size(800, 600) FractalCanvas(), }.open }
} </lang>
Go

<lang go>package main
// Files required to build supporting package raster are found in: // * Bitmap // * Grayscale image // * Xiaolin Wu's line algorithm // * Write a PPM file
import (
"math" "raster"
)
const (
width = 400 height = 300 depth = 8 angle = 12 length = 50 frac = .8
)
func main() {
g := raster.NewGrmap(width, height) ftree(g, width/2, height*9/10, length, 0, depth) g.Bitmap().WritePpmFile("ftree.ppm")
}
func ftree(g *raster.Grmap, x, y, distance, direction float64, depth int) {
x2 := x + distance*math.Sin(direction*math.Pi/180) y2 := y - distance*math.Cos(direction*math.Pi/180) g.AaLine(x, y, x2, y2) if depth > 0 { ftree(g, x2, y2, distance*frac, direction-angle, depth-1) ftree(g, x2, y2, distance*frac, direction+angle, depth-1) }
}</lang>
Haskell
Using
from HackageDB
Using the method of the J contribution <lang haskell>import Graphics.HGL.Window import Graphics.HGL.Run import Control.Arrow import Control.Monad import Data.List
enumBase :: Int -> Int -> Int enumBase n = mapM (enumFromTo 0). replicate n. pred
psPlus (a,b) (p,q) = (a+p, b+q)
toInt :: Double -> Int toInt = fromIntegral.round
intPoint = toInt *** toInt
pts n =
map (map (intPoint.psPlus (100,0)). ((0,300):). scanl1 psPlus. ((r,300):). zipWith (\h a -> (h*cos a, h*sin a)) rs) hs where [r,h,sr,sh] = [50, pi/5, 0.9, 0.75] rs = take n $ map (r*) $ iterate(*sr) sr lhs = map (map (((-1)**).fromIntegral)) $ enumBase n 2 rhs = take n $ map (h*) $ iterate(*sh) 1 hs = map (scanl1 (+). zipWith (*)rhs) lhs
fractalTree :: Int -> IO () fractalTree n =
runWindow "Fractal Tree" (500,600) (\w -> setGraphic w (overGraphics ( map polyline $ pts (n-1))) >> getKey w)</lang>
Use e.g.:
*Main> fractalTree 10
Icon and Unicon
<lang Icon>procedure main() WOpen("size=800,600", "bg=black", "fg=white") | stop("*** cannot open window") drawtree(400,500,-90,9) WDone() end
link WOpen
procedure drawtree(x,y,angle,depth) if depth > 0 then {
x2 := integer(x + cos(dtor(angle)) * depth * 10) y2 := integer(y + sin(dtor(angle)) * depth * 10) DrawLine(x,y,x2,y2) drawtree(x2,y2,angle-20, depth-1) drawtree(x2,y2,angle+20, depth-1) }
return end</lang>
J
<lang j>require'gl2'
L0=: 50 NB. initial length A0=: 1r8p1 NB. initial angle: pi divided by 8 dL=: 0.9 NB. shrink factor for length dA=: 0.75 NB. shrink factor for angle N=: 14 NB. number of branches
L=: L0*dL^1+i.N NB. lengths of line segments
NB. relative angles of successive line segments A=: A0*(dA^i.N) +/\@:*("1) _1 ^ #:i.2 ^ N
NB. end points for each line segment P=: 0 0+/\@,"2 +.*.inv (L0,0),"2 L,"0"1 A
P_C_paint=: gllines_jgl2_ bind (10 + ,/"2 P-"1<./,/P) wd 0 :0
pc P closeok; xywh 0 0 250 300; cc C isigraph rightmove bottommove; pas 0 0; pshow;
)</lang>
See the talk page for some implementation notes.
Java
<lang java>import java.awt.Color; import java.awt.Graphics; import javax.swing.JFrame;
public class FractalTree extends JFrame {
public FractalTree() { super("Fractal Tree"); setBounds(100, 100, 800, 600); setResizable(false); setDefaultCloseOperation(EXIT_ON_CLOSE); }
private void drawTree(Graphics g, int x1, int y1, double angle, int depth) { if (depth == 0) return; int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 10.0); int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 10.0); g.drawLine(x1, y1, x2, y2); drawTree(g, x2, y2, angle - 20, depth - 1); drawTree(g, x2, y2, angle + 20, depth - 1); }
@Override public void paint(Graphics g) { g.setColor(Color.BLACK); drawTree(g, 400, 500, -90, 9); }
public static void main(String[] args) { new FractalTree().setVisible(true); }
}</lang>
JavaScript
Implementation using HTML5 canvas element to draw tree structure. <lang JavaScript><html> <body> <canvas id="canvas" width="600" height="500"></canvas>
<script type="text/javascript"> var elem = document.getElementById('canvas'); var context = elem.getContext('2d');
context.fillStyle = '#000'; context.lineWidth = 1;
var deg_to_rad = Math.PI / 180.0; var depth = 9;
function drawLine(x1, y1, x2, y2, brightness){
context.moveTo(x1, y1); context.lineTo(x2, y2);
}
function drawTree(x1, y1, angle, depth){
if (depth !== 0){ var x2 = x1 + (Math.cos(angle * deg_to_rad) * depth * 10.0); var y2 = y1 + (Math.sin(angle * deg_to_rad) * depth * 10.0); drawLine(x1, y1, x2, y2, depth); drawTree(x2, y2, angle - 20, depth - 1); drawTree(x2, y2, angle + 20, depth - 1); }
}
context.beginPath(); drawTree(300, 500, -90, depth); context.closePath(); context.stroke(); </script>
</body> </html></lang>
jq
The following generates SVG, which can be viewed by following the link below. <lang jq># width and height define the outer dimensions;
- len defines the trunk size;
- scale defines the branch length relative to the trunk;
def main(width; height; len; scale):
def PI: (1|atan)*4;
def precision(n): def pow(k): . as $in | reduce range(0;k) as $i (1; .*$in); if . < 0 then - (-. | precision(n)) else (10|pow(n)) as $power | (. * 10 * $power) | floor as $x | ($x % 10) as $r | ((if $r < 5 then $x else $x + 5 end) / 10 | floor) / $power end;
def p2: precision(2);
def tree(x; y; len; angle): if len < 1 then empty else (x + len * (angle|cos)) as $x2 | (y + len * (angle|sin)) as $y2 | (if len < 10 then 1 else 2 end) as $swidth | (if len < 10 then "blue" else "black" end) as $stroke | "<line x1='\(x|p2)' y1='\(y|p2)' x2='\($x2|p2)' y2='\($y2|p2)' style='stroke:\($stroke); stroke-width:\($swidth)'/>", tree($x2; $y2; len * scale; angle + PI / 5), tree($x2; $y2; len * scale; angle - PI / 5) end ; "<svg width='100%' height='100%' version='1.1' xmlns='http://www.w3.org/2000/svg'>", tree(width / 2; height; len; 3 * PI / 2), "</svg>"
main(1000; 1000; 400; 6/10)</lang>
- Output:
$ jq -r -n -r -f Fractal_tree_svg.jq > Fractal_tree.svg
Liberty BASIC
LB includes Logo-type turtle commands, so can be drawn that way as well as that shown here. <lang lb>
NoMainWin
sw = 640 : sh = 480 WindowWidth = sw+8 : WindowHeight = sh+31 UpperLeftX = (DisplayWidth -sw)/2 UpperLeftY = (DisplayHeight-sh)/2 Open"Fractal Tree" For Graphics_nf_nsb As #g
- g "Down; Color darkgreen; TrapClose halt"
h$ = "#g"
'initial assignments initAngle = Acs(-1)*1.5 'radian equivalent of 270 degrees
theta = 29 * (Acs(-1)/180) 'convert 29 degrees to radians length = 110 'length in pixels depth = 25 'max recursion depth 'draw the tree Call tree h$, 320, 470, initAngle, theta, length, depth #g "Flush; when leftButtonDown halt" 'L-click to exit Wait
Sub halt handle$
Close #handle$ End
End Sub
Sub tree h$, x, y, initAngle, theta, length, depth
Scan newX = Cos(initAngle) * length + x newY = Sin(initAngle) * length + y #h$ "Line ";x;" ";y;" ";newX;" ";newY length = length * .78 depth = depth - 1 If depth > 0 Then Call tree h$, newX, newY, initAngle-theta, theta, length, depth Call tree h$, newX, newY, initAngle+theta, theta, length, depth End If
End Sub
</lang>
Logo
<lang logo>to tree :depth :length :scale :angle
if :depth=0 [stop] setpensize round :depth/2 forward :length right :angle tree :depth-1 :length*:scale :scale :angle left 2*:angle tree :depth-1 :length*:scale :scale :angle right :angle back :length
end
clearscreen tree 10 80 0.7 30</lang>
Mathematica / Wolfram Language
<lang Mathematica>fractalTree[
pt : {_, _}, \[Theta]orient_: \[Pi]/2, \[Theta]sep_: \[Pi]/9, depth_Integer: 9] := Module[{pt2}, If[depth == 0, Return[]]; pt2 = pt + {Cos[\[Theta]orient], Sin[\[Theta]orient]}*depth; DeleteCases[ Flatten@{ Line[{pt, pt2}], fractalTree[pt2, \[Theta]orient - \[Theta]sep, \[Theta]sep, depth - 1], fractalTree[pt2, \[Theta]orient + \[Theta]sep, \[Theta]sep, depth - 1] }, Null ] ]
Graphics[fractalTree[{0, 0}, \[Pi]/2, \[Pi]/9]]
</lang>
NetRexx
<lang NetRexx>/* NetRexx */ options replace format comments java crossref symbols binary
import java.awt.Color import java.awt.Graphics import javax.swing.JFrame
class RFractalTree public extends JFrame
properties constant isTrue = (1 == 1) isFalse = \isTrue -- ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ method RFractalTree() public super('Fractal Tree') setBounds(100, 100, 800, 600) setResizable(isFalse) setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) return -- ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ method drawTree(g = Graphics, x1 = int, y1 = int, angle = double, depth = int) private if depth \= 0 then do x2 = x1 + (int Math.cos(Math.toRadians(angle)) * depth * 10.0) y2 = y1 + (int Math.sin(Math.toRadians(angle)) * depth * 10.0) g.drawLine(x1, y1, x2, y2) drawTree(g, x2, y2, angle - 20, depth - 1) drawTree(g, x2, y2, angle + 20, depth - 1) end return -- ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ method paint(g = Graphics) public g.setColor(Color.BLACK) drawTree(g, 400, 500, -90, 9) return -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method main(args = String[])public static RFractalTree().setVisible(isTrue) return
</lang>
OCaml
<lang ocaml>#directory "+cairo"
- load "bigarray.cma"
- load "cairo.cma"
let img_name = "/tmp/fractree.png" let width = 480 let height = 640
let level = 9 let line_width = 4.0
let color = (1.0, 0.5, 0.0)
let pi = 4.0 *. atan 1.0
let angle_split = pi *. 0.12 let angle_rand = pi *. 0.12
let () =
Random.self_init(); let surf = Cairo.image_surface_create Cairo.FORMAT_RGB24 ~width ~height in let ctx = Cairo.create surf in Cairo.set_antialias ctx Cairo.ANTIALIAS_SUBPIXEL; Cairo.set_line_cap ctx Cairo.LINE_CAP_ROUND;
let draw_line (x,y) (dx,dy) = Cairo.move_to ctx x (float height -. y); Cairo.line_to ctx dx (float height -. dy); Cairo.stroke ctx; in let set_color (r,g,b) v = Cairo.set_source_rgb ctx ~red:(r *. v) ~green:(g *. v) ~blue:(b *. v); in let trans_pos (x,y) len angle = let _x = cos angle and _y = sin angle in (x +. (_x *. len), y +. (_y *. len)) in
let rec loop ~level ~pos ~line_width ~line_len ~angle ~angle_split ~angle_rand ~intc = if level > 0 then begin (* draw the current segment *) Cairo.set_line_width ctx line_width; set_color color intc; let pos_to = trans_pos pos line_len angle in draw_line pos pos_to; (* evolution of the parameters *) let line_width = line_width *. 0.8 and line_len = line_len *. 0.62 and angle_split = angle_split *. 1.02 and angle_rand = angle_rand *. 1.02 and intc = intc *. 0.9 in let next_loop = loop ~level:(pred level) ~pos:pos_to ~intc ~line_width ~line_len ~angle_split ~angle_rand in (* split *) let angle_left = angle +. angle_split +. Random.float angle_rand and angle_right = angle -. angle_split -. Random.float angle_rand in next_loop ~angle:angle_left; next_loop ~angle:angle_right end in
let pos = (float width *. 0.5, float height *. 0.1) and line_len = float height *. 0.3 in loop ~level ~pos ~angle:(pi /. 2.0) ~angle_split ~angle_rand ~line_width ~line_len ~intc:1.0;
Cairo_png.surface_write_to_file surf img_name (*Cairo_png.surface_write_to_channel surf stdout*)</lang>
Perl
using the GD::Simple module. <lang perl>use GD::Simple;
my ($width, $height) = (1000,1000); # image dimension my $scale = 6/10; # branch scale relative to trunk my $length = 400; # trunk size
my $img = GD::Simple->new($width,$height); $img->fgcolor('black'); $img->penSize(1,1);
tree($width/2, $height, $length, 270);
print $img->png;
sub tree
{
my ($x, $y, $len, $angle) = @_;
return if $len < 1;
$img->moveTo($x,$y); $img->angle($angle); $img->line($len);
($x, $y) = $img->curPos();
tree($x, $y, $len*$scale, $angle+35); tree($x, $y, $len*$scale, $angle-35);
}</lang>
Perl 6
Image is created in SVG format. <lang perl6>my ($width, $height) = (1000,1000); # image dimension my $scale = 6/10; # branch scale relative to trunk my $length = 400; # trunk size
say "<?xml version='1.0' encoding='utf-8' standalone='no'?> <!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> <svg width='100%' height='100%' version='1.1' xmlns='http://www.w3.org/2000/svg'>";
tree($width/2, $height, $length, 3*pi/2);
say "</svg>";
multi tree($, $, $length where { $length < 1}, $) {} multi tree($x, $y, $length, $angle) { my ($x2, $y2) = ( $x + $length * $angle.cos, $y + $length * $angle.sin); say "<line x1='$x' y1='$y' x2='$x2' y2='$y2' style='stroke:rgb(0,0,0);stroke-width:1'/>"; tree($x2, $y2, $length*$scale, $angle + pi/5); tree($x2, $y2, $length*$scale, $angle - pi/5); }</lang>
PHP
Image is created with GD module. Code adapted from the JavaScript version. <lang php> <?php header("Content-type: image/png");
$width = 512; $height = 512; $img = imagecreatetruecolor($width,$height); $bg = imagecolorallocate($img,255,255,255); imagefilledrectangle($img, 0, 0, $width, $width, $bg);
$depth = 8; function drawTree($x1, $y1, $angle, $depth){
global $img; if ($depth != 0){ $x2 = $x1 + (int)(cos(deg2rad($angle)) * $depth * 10.0); $y2 = $y1 + (int)(sin(deg2rad($angle)) * $depth * 10.0); imageline($img, $x1, $y1, $x2, $y2, imagecolorallocate($img,0,0,0)); drawTree($x2, $y2, $angle - 20, $depth - 1); drawTree($x2, $y2, $angle + 20, $depth - 1); }
}
drawTree($width/2, $height, -90, $depth);
imagepng($img); imagedestroy($img); ?> </lang>
PicoLisp
This uses the 'brez' line drawing function from Bitmap/Bresenham's line algorithm#PicoLisp. <lang PicoLisp>(load "@lib/math.l")
(de fractalTree (Img X Y A D)
(unless (=0 D) (let (R (*/ A pi 180.0) DX (*/ (cos R) D 0.2) DY (*/ (sin R) D 0.2)) (brez Img X Y DX DY) (fractalTree Img (+ X DX) (+ Y DY) (+ A 30.0) (dec D)) (fractalTree Img (+ X DX) (+ Y DY) (- A 30.0) (dec D)) ) ) )
(let Img (make (do 300 (link (need 400 0)))) # Create image 400 x 300
(fractalTree Img 200 300 -90.0 10) # Draw tree (out "img.pbm" # Write to bitmap file (prinl "P1") (prinl 400 " " 300) (mapc prinl Img) ) )</lang>
PostScript
<lang postscript>%!PS %%BoundingBox: 0 0 300 300 %%EndComments /origstate save def /ld {load def} bind def /m /moveto ld /g /setgray ld /t /translate ld /r /rotate ld /l /lineto ld /rl /rlineto ld /s /scale ld %%EndProlog /PerturbateAngle {} def /PerturbateLength {} def % ** To add perturbations, define properly PerturbateAngle and PerturbateLength, e.g. % /PerturbateAngle {realtime 20 mod realtime 2 mod 1 eq {add} {sub} ifelse} def % /PerturbateLength {realtime 10 mod 100 div realtime 2 mod 1 eq {add} {sub} ifelse} def /fractree { % [INITLENGTH, SPLIT, SFACTOR, BRANCHES]
dup 3 get 0 gt { 0 0 m dup 0 get 0 exch l gsave dup 0 get 0 exch t dup 1 get PerturbateAngle r dup 2 get dup PerturbateLength s dup aload pop 1 sub 4 array astore fractree stroke grestore gsave dup 0 get 0 exch t dup 1 get neg PerturbateAngle r dup 2 get dup PerturbateLength s dup aload pop 1 sub 4 array astore fractree stroke grestore } if pop
} def % /BRANCHES 14 def /INITLENGTH 50 def /SPLIT 35 def /SFACTOR .75 def % % BB check %0 0 m 300 0 rl 0 300 rl -300 0 rl closepath stroke % 0 g 150 0 t [INITLENGTH SPLIT SFACTOR BRANCHES] fractree stroke % showpage origstate restore %%EOF</lang>
Shorter version:<lang postscript>%!PS-Adobe-3.0 %%BoundingBox: 0 0 300 300 /!0 { dup 1 sub dup 0 gt } def /trunk { 0 0 moveto 0 60 translate 0 0 lineto stroke } def
/branch { gsave scale rotate dup d exch sub d div setgray tree grestore } def /L { 30 .8 .8 branch } def /M {-10 .7 .7 branch } def /R {-35 .7 .7 branch } def /tree { trunk !0 { L M R } if pop } def
/d 10 def 5 setlinewidth 1 setlinecap 170 20 translate d tree pop %%EOF</lang>
POV-Ray
<lang povray>#include "colors.inc"
- include "transforms.inc"
- declare CamLoc = <0, 5, 0>;
- declare CamLook = <0,0,0>;
camera {
location CamLoc look_at CamLook rotate y*90
}
light_source {
CamLoc color White
}
- declare Init_Height = 10;
- declare Spread_Ang = 35;
- declare Branches = 14;
- declare Scaling_Factor = 0.75;
- macro Stick(P0, P1)
cylinder { P0, P1, 0.02 texture { pigment { Green } } }
- end
- macro FractalTree(O, D, S, R, B)
#if (B > 0) Stick(O, O+D*S) FractalTree(O+D*S, vtransform(D, transform{rotate y*R}), S*Scaling_Factor, R, B-1) FractalTree(O+D*S, vtransform(D, transform{rotate -y*R}), S*Scaling_Factor, R, B-1) #end
- end
union {
FractalTree(<-2,0,0>, <1,0,0>, 1, Spread_Ang, Branches)
}</lang>
Prolog
SWI-Prolog has a graphic interface : XPCE. <lang Prolog>fractal :- new(D, window('Fractal')), send(D, size, size(800, 600)), drawTree(D, 400, 500, -90, 9), send(D, open).
drawTree(_D, _X, _Y, _Angle, 0).
drawTree(D, X1, Y1, Angle, Depth) :-
X2 is X1 + cos(Angle * pi / 180.0) * Depth * 10.0, Y2 is Y1 + sin(Angle * pi / 180.0) * Depth * 10.0,
new(Line, line(X1, Y1, X2, Y2, none)), send(D, display, Line), A1 is Angle - 30, A2 is Angle + 30, De is Depth - 1,
drawTree(D, X2, Y2, A1, De), drawTree(D, X2, Y2, A2, De).
</lang>
PureBasic
<lang PureBasic>#Spread_Ang = 35
- Scaling_Factor = 0.75
- Deg_to_Rad = #PI / 180
- SizeH = 500
- SizeV = 375
- Init_Size = 100
Procedure drawTree(x1, y1, Size, theta, depth)
Protected x2 = x1 + Cos(theta * #Deg_to_Rad) * Size, y2 = y1 + Sin(theta * #Deg_to_Rad) * Size LineXY(x1, y1, x2, y2, RGB(255, 255, 255)) If depth <= 0 ProcedureReturn EndIf ;draw left branch drawTree(x2, y2, Size * #Scaling_Factor, theta - #Spread_Ang, depth - 1) ;draw right branch drawTree(x2, y2, Size * #Scaling_Factor, theta + #Spread_Ang, depth - 1)
EndProcedure
OpenWindow(0, 0, 0, #SizeH, #SizeV, "Fractal Tree", #PB_Window_SystemMenu)
Define fractal = CreateImage(#PB_Any, #SizeH, #SizeV, 32)
ImageGadget(0, 0, 0, 0, 0, ImageID(fractal))
If StartDrawing(ImageOutput(fractal))
drawTree(#SizeH / 2, #SizeV, #Init_Size, -90, 9) StopDrawing() SetGadgetState(0, ImageID(fractal))
EndIf
Repeat: Until WaitWindowEvent(10) = #PB_Event_CloseWindow</lang>
Python
<lang python>import pygame, math
pygame.init() window = pygame.display.set_mode((600, 600)) pygame.display.set_caption("Fractal Tree") screen = pygame.display.get_surface()
def drawTree(x1, y1, angle, depth):
if depth: x2 = x1 + int(math.cos(math.radians(angle)) * depth * 10.0) y2 = y1 + int(math.sin(math.radians(angle)) * depth * 10.0) pygame.draw.line(screen, (255,255,255), (x1, y1), (x2, y2), 2) drawTree(x2, y2, angle - 20, depth - 1) drawTree(x2, y2, angle + 20, depth - 1)
def input(event):
if event.type == pygame.QUIT: exit(0)
drawTree(300, 550, -90, 9) pygame.display.flip() while True:
input(pygame.event.wait())</lang>
Racket

<lang racket>
- lang racket
(require graphics/turtles)
(define (tree n)
(when (> n 1) (draw (/ n 2)) (tprompt (split* (turn 60) (turn -60)) (tree (/ n 2))) (draw (/ n 2)) (turn 5) (tree (- n 1))))
(turtles #t) (move 100) (turn 90) (move -200) (tree 35) (save-turtle-bitmap "tree.png" 'png) </lang>
Ruby
<lang Ruby>Shoes.app(:title => "Fractal Tree", :width => 600, :height => 600) do
background "#fff" stroke "#000" @deg_to_rad = Math::PI / 180.0 def drawTree(x1, y1, angle, depth) if depth != 0 x2 = x1 + (Math.cos(angle * @deg_to_rad) * depth * 10.0).to_i y2 = y1 + (Math.sin(angle * @deg_to_rad) * depth * 10.0).to_i line x1, y1, x2, y2 drawTree(x2, y2, angle - 20, depth - 1) drawTree(x2, y2, angle + 20, depth - 1) end end drawTree(300,550,-90,9)
end</lang>
Scala
Adapted from the Java version. Screenshot below. <lang scala>import swing._ import java.awt.{RenderingHints, BasicStroke, Color}
object FractalTree extends SimpleSwingApplication {
val DEPTH = 9
def top = new MainFrame { contents = new Panel { preferredSize = new Dimension(600, 500)
override def paintComponent(g: Graphics2D) { draw(300, 460, -90, DEPTH)
def draw(x1: Int, y1: Int, angle: Double, depth: Int) { if (depth > 0) { val x2 = x1 + (math.cos(angle.toRadians) * depth * 10).toInt val y2 = y1 + (math.sin(angle.toRadians) * depth * 10).toInt
g.setColor(Color.getHSBColor(0.25f - depth * 0.125f / DEPTH, 0.9f, 0.6f)) g.setStroke(new BasicStroke(depth)) g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON) g.drawLine(x1, y1, x2, y2)
draw(x2, y2, angle - 20, depth - 1) draw(x2, y2, angle + 20, depth - 1) } } } } }
Seed7
<lang seed7>$ include "seed7_05.s7i";
include "float.s7i"; include "math.s7i"; include "draw.s7i"; include "keybd.s7i";
const float: DEG_TO_RAD is PI / 180.0;
const proc: drawTree (in integer: x1, in integer: y1, in float: angle, in integer: depth) is func
local var integer: x2 is 0; var integer: y2 is 0; begin if depth <> 0 then x2 := x1 + trunc(cos(angle * DEG_TO_RAD) * flt(depth * 10)); y2 := y1 + trunc(sin(angle * DEG_TO_RAD) * flt(depth * 10)); lineTo(x1, y1, x2, y2, white); drawTree(x2, y2, angle - 20.0, depth - 1); drawTree(x2, y2, angle + 20.0, depth - 1); end if; end func;
const proc: main is func
begin screen(600, 500); clear(curr_win, black); KEYBOARD := GRAPH_KEYBOARD; drawTree(300, 470, -90.0, 9); ignore(getc(KEYBOARD)); end func;</lang>
Original source: [1]
Sidef
<lang ruby>func tree(img, x, y, scale=6/10, len=400, angle=270) {
len < 1 && return;
img.moveTo(x, y); img.angle(angle); img.line(len);
var (x1, y1) = img.curPos; tree(img, x1, y1, scale, len*scale, angle+35); tree(img, x1, y1, scale, len*scale, angle-35);
}
require 'GD::Simple';
var (width=1000, height=1000); var img = %s'GD::Simple'.new(width, height); img.fgcolor('black'); img.penSize(1, 1);
tree(img, width/2, height);
var file = %f'tree.png'; var fh = file.open('>:raw'); fh.print(img.png); fh.close;</lang>
Smalltalk
This example is coded for Squeak Smalltalk.
<lang smalltalk> Object subclass: #FractalTree
instanceVariableNames: classVariableNames: poolDictionaries: category: 'RosettaCode'
</lang>
Methods for FractalTree class:
<lang smalltalk> tree: aPoint length: aLength angle: anAngle
| p a | (aLength > 10) ifTrue: [ p := Pen new. p up. p goto: aPoint. p turn: anAngle. p down. 5 timesRepeat: [ p go: aLength / 5. p turn: 5. ]. a := anAngle - 30. 3 timesRepeat: [ self tree: p location length: aLength * 0.7 angle: a. a := a + 30. ] ].
draw
Display restoreAfter: [ Display fillWhite. self tree: 700@700 length: 200 angle: 0. ]
</lang>
Now open a new Workspace and enter:
<lang smalltalk> FractalTree new draw. </lang>
SVG
In the same style as Dragon curve#SVG. SVG has no parameterized definitions, so the recursion must be unrolled.
<lang xml><?xml version="1.0" standalone="yes"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="320"> <style type="text/css"><![CDATA[ line { stroke: black; stroke-width: .05; } circle { fill: black; } ]]></style>
<defs>
<g id="stem"> <line x1="0" y1="0" x2="0" y2="-1"/> </g> <g id="l0"><use xlink:href="#stem"/></g> <g id="l1"> <use xlink:href="#l0" transform="translate(0, -1) rotate(-35) scale(.7)"/> <use xlink:href="#l0" transform="translate(0, -1) rotate(+35) scale(.7)"/> <use xlink:href="#stem"/></g> <g id="l2"> <use xlink:href="#l1" transform="translate(0, -1) rotate(-35) scale(.7)"/> <use xlink:href="#l1" transform="translate(0, -1) rotate(+35) scale(.7)"/> <use xlink:href="#stem"/></g> <g id="l3"> <use xlink:href="#l2" transform="translate(0, -1) rotate(-35) scale(.7)"/> <use xlink:href="#l2" transform="translate(0, -1) rotate(+35) scale(.7)"/> <use xlink:href="#stem"/></g> <g id="l4"> <use xlink:href="#l3" transform="translate(0, -1) rotate(-35) scale(.7)"/> <use xlink:href="#l3" transform="translate(0, -1) rotate(+35) scale(.7)"/> <use xlink:href="#stem"/></g> <g id="l5"> <use xlink:href="#l4" transform="translate(0, -1) rotate(-35) scale(.7)"/> <use xlink:href="#l4" transform="translate(0, -1) rotate(+35) scale(.7)"/> <use xlink:href="#stem"/></g> <g id="l6"> <use xlink:href="#l5" transform="translate(0, -1) rotate(-35) scale(.7)"/> <use xlink:href="#l5" transform="translate(0, -1) rotate(+35) scale(.7)"/> <use xlink:href="#stem"/></g> <g id="l7"> <use xlink:href="#l6" transform="translate(0, -1) rotate(-35) scale(.7)"/> <use xlink:href="#l6" transform="translate(0, -1) rotate(+35) scale(.7)"/> <use xlink:href="#stem"/></g> <g id="l8"> <use xlink:href="#l7" transform="translate(0, -1) rotate(-35) scale(.7)"/> <use xlink:href="#l7" transform="translate(0, -1) rotate(+35) scale(.7)"/> <use xlink:href="#stem"/></g> <g id="l9"> <use xlink:href="#l8" transform="translate(0, -1) rotate(-35) scale(.7)"/> <use xlink:href="#l8" transform="translate(0, -1) rotate(+35) scale(.7)"/> <use xlink:href="#stem"/></g>
</defs>
<g transform="translate(200, 320) scale(100)">
<use xlink:href="#l9"/>
</g>
</svg></lang>
Swift
Image - Link, since uploads seem to be disabled currently. In a playground: <lang swift> import UIKit
extension CGFloat {
func degrees_to_radians() -> CGFloat { return CGFloat(M_PI) * self / 180.0 }
}
extension Double {
func degrees_to_radians() -> Double { return Double(M_PI) * self / 180.0 }
}
class Tree: UIView {
func drawTree(x1: CGFloat, y1: CGFloat, angle: CGFloat, depth:Int){ if depth == 0 { return } let ang = angle.degrees_to_radians() let x2:CGFloat = x1 + ( cos(ang) as CGFloat) * CGFloat(depth) * (self.frame.width / 60) let y2:CGFloat = y1 + ( sin(ang) as CGFloat) * CGFloat(depth) * (self.frame.width / 60) let line = drawLine(x1, y1: y1, x2: x2, y2: y2) line.stroke() drawTree(x2, y1: y2, angle: angle - 20, depth: depth - 1) drawTree(x2, y1: y2, angle: angle + 20, depth: depth - 1) } func drawLine(x1:CGFloat, y1:CGFloat, x2:CGFloat, y2:CGFloat) -> UIBezierPath { let path = UIBezierPath() path.moveToPoint(CGPoint(x: x1,y: y1)) path.addLineToPoint(CGPoint(x: x2,y: y2)) path.lineWidth = 1 return path } override func drawRect(rect: CGRect) { let color = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0) color.set() drawTree(self.frame.width / 2 , y1: self.frame.height * 0.8, angle: -90 , depth: 9 ) }
}
let tree = Tree(frame: CGRectMake(0, 0, 300, 300))
tree
</lang>
Tcl
<lang tcl>package require Tk
set SIZE 800 set SCALE 4.0 set BRANCHES 14 set ROTATION_SCALE 0.85 set INITIAL_LENGTH 50.0
proc draw_tree {w x y dx dy size theta depth} {
global SCALE ROTATION_SCALE $w create line $x $y [expr {$x + $dx*$size}] [expr {$y + $dy*$size}] if {[incr depth -1] >= 0} {
set x [expr {$x + $dx*$size}] set y [expr {$y + $dy*$size}] set ntheta [expr {$theta * $ROTATION_SCALE}]
# Draw left branch draw_tree $w $x $y \ [expr {$dx*cos($theta) + $dy*sin($theta)}] \ [expr {$dy*cos($theta) - $dx*sin($theta)}] \ [expr {$size * (rand() + $SCALE - 1) / $SCALE}] $ntheta $depth # Draw right branch draw_tree $w $x $y \ [expr {$dx*cos(-$theta) + $dy*sin(-$theta)}] \ [expr {$dy*cos(-$theta) - $dx*sin(-$theta)}] \ [expr {$size * (rand() + $SCALE - 1) / $SCALE}] $ntheta $depth
}
}
pack [canvas .c -width $SIZE -height $SIZE] draw_tree .c [expr {$SIZE/2}] [expr {$SIZE-10}] 0.0 -1.0 $INITIAL_LENGTH \
[expr {3.1415927 / 8}] $BRANCHES</lang>
TUSCRIPT
Image is created in SVG-format <lang tuscript> $$ MODE TUSCRIPT dest="fracaltree.svg" ERROR/STOP CREATE (dest,fdf-o,-std-) ACCESS d: WRITE/ERASE/RECORDS/UTF8 $dest s,text MODE DATA $$ header=* <?xml version="1.0" standalone="yes"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="320"> <style type="text/css"><![CDATA[ line { stroke: brown; stroke-width: .05; } ]]></style>
$$ WRITE/NEXT d header $$ defsbeg=* <defs>
<g id="stem"> <line x1="0" y1="0" x2="0" y2="-1"/> </g> <g id="l"><use xlink:href="#stem"/></g>
$$ WRITE/NEXT d defsbeg $$ LOOP n=10,21 $$ id=n+1,lastnr=VALUE(n) $$ g=*
<g id="{id}"> <use xlink:href="#{n}" transform="translate(0, -1) rotate(-35) scale(.7)"/> <use xlink:href="#{n}" transform="translate(0, -1) rotate(+35) scale(.7)"/> <use xlink:href="#stem"/></g>
$$ WRITE/NEXT d g $$ ENDLOOP $$ defsend = * </defs> <g transform="translate(200, 320) scale(100)">
<use xlink:href="#{lastnr}"/>
</g> $$ MODE TUSCRIPT WRITE/NEXT d defsend WRITE/NEXT d "</svg>" ENDACCESS d </lang>
XPL0

<lang XPL0>include c:\cxpl\codes;
proc DrawBranch(Lev, Dir, Len, X, Y); int Lev; real Dir, Len; int X, Y; int Red, Grn; [Move(X, Y); X:= X + fix(Len*Cos(Dir)); Y:= Y + fix(Len*Sin(Dir)); Red:= 255-Lev*8; Grn:= Lev*12+100; Line(X, Y, Red<<16+Grn<<8); if Lev < 12 then \limit level of recursion
[DrawBranch(Lev+1, Dir-0.4, Len*0.8, X, Y); \left DrawBranch(Lev+1, Dir+0.1, Len*0.8, X, Y); \right ];
];
[SetVid($112); \set 640x480x24 video graphics mode DrawBranch(0, -3.14159/2.0, 80.0, 360, 460); if ChIn(1) then []; \wait for keystroke SetVid(3); \restore normal text mode ]</lang>
zkl
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl
<lang zkl>fcn fractalTree(){
scale:=0.76; sizeX:=400; sizeY:=300; bitmap:=PPM(sizeX*2,sizeY*2,0xFF|FF|FF); branch:='wrap(x1,y1,size,angle,depth){ ar:=angle.toRad(); x2:=x1 - size*ar.cos(); y2:=y1 + size*ar.sin(); color:=(0xff-depth*8).shiftLeft(16) + (depth*12+100).shiftLeft(8); bitmap.line(x1,y1, x2,y2, color); if(depth){ self.fcn(x2,y2,scale*size,angle - 30,depth - 1,vm.pasteArgs(5));
self.fcn(x2,y2,scale*size,angle + 8, depth - 1,vm.pasteArgs(5));
} }; branch(sizeX,0,sizeY/2,90.0,10); bitmap.write(File("foo.ppm","wb"));
}();</lang> The funkyness (pasteArgs) in the recursion (self.fcn) is due to the closure ('wrap): the closed over args are stashed in the arglist, they need to be added to the parameters when recursing.
- Output:
See the XPL0 image and imagine it more orange than green: http://www.zenkinetic.com/Images/RosettaCode/fractalTree.jpg
- Programming Tasks
- Fractals
- Raster graphics operations
- Recursion
- AutoHotkey
- GDIP
- BASIC256
- BBC BASIC
- C
- SDL
- SGE
- Cairo
- C++
- Clojure
- Swing
- AWT
- Common Lisp
- Lispbuilder-sdl
- D
- F Sharp
- Fantom
- Go
- Haskell
- HGL
- Icon
- Unicon
- Icon Programming Library
- J
- Java
- JavaScript
- Jq
- Liberty BASIC
- Logo
- Mathematica
- Wolfram Language
- NetRexx
- OCaml
- Ocaml-cairo
- Perl
- Perl 6
- PHP
- PicoLisp
- PostScript
- POV-Ray
- Prolog
- PureBasic
- Python
- Pages with broken file links
- Pygame
- Racket
- Ruby
- Shoes
- Scala
- Seed7
- Sidef
- Smalltalk
- SVG
- Swift
- Tcl
- Tk
- TUSCRIPT
- XPL0
- Zkl
- Geometry