Brownian tree: Difference between revisions

m
(→‎{{header|Processing}}: black background needed for white tree version (change made in a previous edit))
 
(44 intermediate revisions by 17 users not shown)
Line 1:
[[Category:Raster graphics operations]]
[[Category:Geometry]]
{{Wikipedia|Brownian_tree}}
{{task|Fractals}}
[[Category:Raster graphics operations]]
[[File:Brownian_tree.jpg|450px||right]]
 
Line 16 ⟶ 17:
 
<br>Because of the lax rules governing the random nature of the particle's placement and motion, no two resulting trees are really expected to be the same, or even necessarily have the same general shape. <br><br>
=={{header|Action!}}==
Calculations on a real Atari 8-bit computer take quite long time. It is recommended to use an emulator capable with increasing speed of Atari CPU.
<syntaxhighlight lang="action!">BYTE FUNC CheckNeighbors(CARD x BYTE y)
IF Locate(x-1,y-1)=1 THEN RETURN (1) FI
IF Locate(x,y-1)=1 THEN RETURN (1) FI
IF Locate(x+1,y-1)=1 THEN RETURN (1) FI
IF Locate(x-1,y)=1 THEN RETURN (1) FI
IF Locate(x+1,y)=1 THEN RETURN (1) FI
IF Locate(x-1,y+1)=1 THEN RETURN (1) FI
IF Locate(x,y+1)=1 THEN RETURN (1) FI
IF Locate(x+1,y+1)=1 THEN RETURN (1) FI
RETURN (0)
 
PROC DrawTree()
DEFINE MAXW="255"
DEFINE MINX="1"
DEFINE MAXX="318"
DEFINE MINY="1"
DEFINE MAXY="190"
BYTE CH=$02FC
CARD x,l,r
BYTE y,t,b,w,h,dx,dy,m=[20]
 
x=160 y=96
Plot(x,y)
l=x-m r=x+m
t=y-m b=y+m
w=r-l+1 h=b-t+1
DO
DO
x=Rand(w)+l y=Rand(h)+t
UNTIL Locate(x,y)=0
OD
 
WHILE CheckNeighbors(x,y)=0
DO
DO
dx=Rand(3) dy=Rand(3)
UNTIL dx#2 OR dy#2
OD
 
IF dx=0 THEN
IF x>l THEN x==-1
ELSE x=r-1
FI
ELSEIF dx=1 THEN
IF x<r THEN x==+1
ELSE x=l+1
FI
FI
IF dy=0 THEN
IF y>t THEN y==-1
ELSE y=b-1
FI
ELSEIF dy=1 THEN
IF y<b THEN y==+1
ELSE y=t+1
FI
FI
OD
 
Plot(x,y)
IF l>MINX AND l+m>x AND w<MAXW THEN
l==-1 w==+1
FI
IF r<MAXX AND r-m<x AND w<MAXW THEN
r==+1 w==+1
FI
IF t>MINY AND t+m>y THEN
t==-1 h==+1
FI
IF b<MAXY AND b-m<y THEN
b==+1 h==+1
FI
 
Poke(77,0) ;turn off the attract mode
UNTIL CH#$FF ;until key pressed
OD
CH=$FF
RETURN
 
PROC Main()
BYTE COLOR1=$02C5,COLOR2=$02C6
 
Graphics(8+16)
Color=1
COLOR1=$0E
COLOR2=$02
 
DrawTree()
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Brownian_tree.png Screenshot from Atari 8-bit computer]
=={{header|Ada}}==
{{libheader|SDLAda}}
<langsyntaxhighlight Adalang="ada">with Ada.Numerics.Discrete_Random;
 
with SDL.Video.Windows.Makers;
Line 143 ⟶ 237:
Window.Finalize;
SDL.Finalise;
end Brownian_Tree;</langsyntaxhighlight>
 
=={{header|Applesoft BASIC}}==
Uses XDRAW to plot to Hi-res GRaphics, in fullscreen [POKE 49234,0] 280 x 192, effectively 140 x 192 because colors stretch over two pixels, using a single pixel shape. The POKEs create one shape in a shape table starting at address 768 and point addresses 232 and 233 to this address. Address 234 is the collision counter which is used to detect if the randomly placed seed has hit anything and if the moving seed has collided with the tree. Plotting the seed creates an animation effect of the seed moving around in it's Brownian way.<langsyntaxhighlight lang="applesoftbasic">0GOSUB2:FORQ=0TOTSTEP0:X=A:Y=B:FORO=0TOTSTEP0:XDRAWTATX,Y:X=INT(RND(T)*J)*Z:Y=INT(RND(T)*H):XDRAWTATX,Y:O=PEEK(C)>0:NEXTO:FORP=0TOTSTEP0:A=X:B=Y:R=INT(RND(T)*E):X=X+X(R):Y=Y+Y(R):IFX<0ORX>MORY<0ORY>NTHENNEXTQ
1 XDRAW T AT X,Y:P = NOT PEEK (C): XDRAW T AT A,B: NEXT P: XDRAW T AT X,Y:Q = A = 0 OR A = M OR B = 0 OR B = N: NEXT Q: END
2 T = 1:Z = 2:E = 8:C = 234
Line 161 ⟶ 254:
13 POKE 232,0: POKE 233,3
14 HGR : POKE 49234,0
15 ROT= 0: SCALE= 1: RETURN</langsyntaxhighlight>
=={{header|ATS}}==
 
[[File:Brownian tree.2023.05.07.18.48.00.png|thumb|alt=A brownian tree, black on white.]]
[[File:Brownian tree.2023.05.07.18.48.25.png|thumb|alt=A brownian tree, black on white.]]
[[File:Brownian tree.2023.05.07.18.49.01.png|thumb|alt=A brownian tree, black on white.]]
[[File:Brownian tree.2023.05.07.18.49.34.png|thumb|alt=A brownian tree, black on white.]]
 
The program outputs a Portable Arbitrary Map. Shown are some examples for 10000 particles on 300x300 grid.
 
<syntaxhighlight lang="ats">
(* This program pours all the particles onto the square at once, with
one of them as seed, and then lets the particles move around.
 
Compile with
patscc -std=gnu2x -D_GNU_SOURCE -g -O3 -DATS_MEMALLOC_LIBC brownian_tree_task.dats
 
You may need the -D_GNU_SOURCE to get a declaration of the
random(3) function. *)
(*------------------------------------------------------------------*)
 
%{^
#include <stdlib.h>
%}
 
#include "share/atspre_staload.hats"
 
#define NIL list_nil ()
#define :: list_cons
 
extern castfn lint2int : {i : int} lint i -<> int i
implement g1int2int<lintknd,intknd> i = lint2int i
 
extern fn random () : [i : nat] lint i = "mac#random"
extern fn srandom (seed : uint) : void = "mac#srandom"
extern fn atoi (s : string) : int = "mac#atoi"
 
(*------------------------------------------------------------------*)
 
datatype grid_position =
| Wall
| Empty
| Sticky
| Freely_moving
 
fn {}
grid_position_equal
(x : grid_position,
y : grid_position)
:<> bool =
case+ x of
| Wall () => (case+ y of Wall () => true | _ => false)
| Empty () => (case+ y of Empty () => true | _ => false)
| Sticky () => (case+ y of Sticky () => true | _ => false)
| Freely_moving () =>
(case+ y of Freely_moving () => true | _ => false)
 
fn {}
grid_position_notequal
(x : grid_position,
y : grid_position)
:<> bool =
~grid_position_equal (x, y)
 
overload = with grid_position_equal
overload <> with grid_position_notequal
 
(*------------------------------------------------------------------*)
 
abstype container (w : int, h : int) = ptr
 
local
 
typedef _container (w : int, h : int) =
'{M = matrixref (grid_position, w, h),
w = int w,
h = int h}
 
in (* local *)
 
assume container (w, h) = _container (w, h)
 
fn {}
container_make
{w, h : pos}
(w : int w,
h : int h)
: container (w, h) =
'{M = matrixref_make_elt<grid_position> (i2sz w, i2sz h, Empty),
w = w, h = h}
 
fn {}
container_width
{w, h : pos}
(C : container (w, h))
: int w =
C.w
 
fn {}
container_height
{w, h : pos}
(C : container (w, h))
: int h =
C.h
 
fn {}
container_get_at
{w, h : pos}
(C : container (w, h),
x : intBtwe (~1, w),
y : intBtwe (~1, h))
: grid_position =
let
macdef M = C.M
in
if (0 <= x) * (x < C.w) * (0 <= y) * (y < C.h) then
M[x, C.h, y]
else
Wall
end
 
fn
container_set_at
{w, h : pos}
(C : container (w, h),
x : intBtw (0, w),
y : intBtw (0, h),
gpos : grid_position)
: void =
let
macdef M = C.M
in
M[x, C.h, y] := gpos
end
 
end (* local *)
 
overload width with container_width
overload height with container_height
overload [] with container_get_at
overload [] with container_set_at
 
(*------------------------------------------------------------------*)
 
fn
random_direction () :
@(intBtwe (~1, 1), intBtwe (~1, 1)) =
let
val r1 = random ()
val r2 = random ()
val dx : intBtwe (0, 2) = g1i2i (r1 \nmod 3)
and dy : intBtwe (0, 2) = g1i2i (r2 \nmod 3)
in
@(pred dx, pred dy)
end
 
fn
in_sticky_position
{w, h : pos}
(C : container (w, h),
x : intBtw (0, w),
y : intBtw (0, h))
: bool =
(C[pred x, pred y] = Sticky () ||
C[pred x, y] = Sticky () ||
C[pred x, succ y] = Sticky () ||
C[succ x, pred y] = Sticky () ||
C[succ x, y] = Sticky () ||
C[succ x, succ y] = Sticky () ||
C[x, pred y] = Sticky () ||
C[x, succ y] = Sticky ())
 
fn
find_placement_for_another_particle
{w, h : pos}
(C : container (w, h))
: @(intBtw (0, w), intBtw (0, h)) =
let
val w = width C and h = height C
 
fun
loop () : @(intBtw (0, w), intBtw (0, h)) =
let
val r1 = random ()
val r2 = random ()
val x : intBtw (0, w) = g1i2i (r1 \nmod w)
and y : intBtw (0, h) = g1i2i (r2 \nmod h)
in
if C[x, y] <> Empty () then
loop ()
else
@(x, y)
end
in
loop ()
end
 
fn
move_particles
{w, h : pos}
(C : container (w, h),
particles : &List0 @(intBtw (0, w), intBtw (0, h)) >> _)
: void =
let
typedef coords = @(intBtw (0, w), intBtw (0, h))
 
fun
loop {n : nat} .<n>.
(particles : list (coords, n),
new_lst : List0 coords)
: List0 coords =
case+ particles of
| NIL => new_lst
| @(x0, y0) :: tl =>
let
val @(dx, dy) = random_direction ()
val x1 = x0 + dx and y1 = y0 + dy
in
if C[x1, y1] = Empty () then
let
val () = assertloc (0 <= x1)
val () = assertloc (x1 < width C)
val () = assertloc (0 <= y1)
val () = assertloc (y1 < height C)
in
C[x1, y1] := C[x0, y0];
C[x0, y0] := Empty ();
loop (tl, @(x1, y1) :: new_lst)
end
else
(* Our rule is: if there is anything where it WOULD have
moved to, then the particle does not move. *)
loop (tl, @(x0, y0) :: new_lst)
end
in
particles := loop (particles, NIL)
end
 
fn
find_which_particles_are_stuck
{w, h : pos}
(C : container (w, h),
particles : &List0 @(intBtw (0, w), intBtw (0, h)) >> _)
: void =
(* Our rule is: if a particle is next to something that ALREADY was
stuck, then it too is stuck. Otherwise it remains free. *)
let
typedef coords = @(intBtw (0, w), intBtw (0, h))
 
fun
loop {n : nat} .<n>.
(particles : list (coords, n),
new_lst : List0 coords)
: List0 coords =
case+ particles of
| NIL => new_lst
| @(x, y) :: tl =>
if in_sticky_position (C, x, y) then
begin
C[x, y] := Sticky ();
loop (tl, new_lst)
end
else
loop (tl, @(x, y) :: new_lst)
in
particles := loop (particles, NIL)
end
 
fn
pour_particles
{w, h : pos}
{n : nat}
(C : container (w, h),
n : int n,
free_particles : &List0 @(intBtw (0, w), intBtw (0, h))?
>> List0 @(intBtw (0, w), intBtw (0, h)))
: void =
if n = 0 then
free_particles := NIL
else
let
typedef coords = @(intBtw (0, w), intBtw (0, h))
 
fun
loop {i : nat | i <= n - 1}
.<(n - 1) - i>.
(particles : list (coords, i),
i : int i)
: list (coords, n - 1) =
if i = pred n then
particles
else
let
val @(x, y) = find_placement_for_another_particle C
in
C[x, y] := Freely_moving;
loop (@(x, y) :: particles, succ i)
end
 
val @(xseed, yseed) = find_placement_for_another_particle C
in
C[xseed, yseed] := Sticky ();
free_particles := loop (NIL, 0)
end
 
fn
go_until_all_particles_are_stuck
{w, h : pos}
(C : container (w, h),
free_particles : List0 @(intBtw (0, w), intBtw (0, h)))
: void =
let
typedef coords = @(intBtw (0, w), intBtw (0, h))
 
fun
loop (free_particles : &List0 coords >> _) : void =
case+ free_particles of
| NIL => ()
| _ :: _ =>
begin
move_particles (C, free_particles);
find_which_particles_are_stuck (C, free_particles);
loop free_particles
end
 
var free_particles : List0 coords = free_particles
in
find_which_particles_are_stuck (C, free_particles);
loop free_particles
end
 
fn
build_a_tree {w, h : pos}
{n : nat}
(w : int w,
h : int h,
n : int n)
: container (w, h) =
let
val C = container_make (w, h)
var free_particles : List0 @(intBtw (0, w), intBtw (0, h))
in
pour_particles (C, n, free_particles);
go_until_all_particles_are_stuck (C, free_particles);
C
end
 
fn
write_a_PAM_image
{w, h : pos}
(outf : FILEref,
C : container (w, h),
seed : uint)
: void =
let
val w = width C and h = height C
 
fun
count_particles
{x, y : nat | x <= w; y <= h}
.<h - y, w - x>.
(x : int x,
y : int y,
n : int)
: int =
if y = h then
n
else if x = w then
count_particles (0, succ y, n)
else if C[x, y] = Empty () then
count_particles (succ x, y, n)
else
count_particles (succ x, y, succ n)
 
fun
loop {x, y : nat | x <= w; y <= h}
.<h - y, w - x>.
(x : int x,
y : int y)
: void =
if y = h then
()
else if x = w then
loop (0, succ y)
else
begin
fprint_val<char>
(outf, if C[x, y] = Empty () then '\1' else '\0');
loop (succ x, y)
end
in
fprintln! (outf, "P7");
fprintln! (outf, "# Number of particles = ",
count_particles (0, 0, 0));
fprintln! (outf, "# Seed = ", seed);
fprintln! (outf, "WIDTH ", width C);
fprintln! (outf, "HEIGHT ", height C);
fprintln! (outf, "DEPTH 1");
fprintln! (outf, "MAXVAL 1");
fprintln! (outf, "TUPLTYPE BLACKANDWHITE");
fprintln! (outf, "ENDHDR");
loop (0, 0)
end
 
(*------------------------------------------------------------------*)
 
implement
main0 (argc, argv) =
let
val args = list_vt2t (listize_argc_argv (argc, argv))
val nargs = argc
in
if nargs <> 5 then
begin
fprintln! (stderr_ref, "Usage: ", args[0],
" width height num_particles seed");
exit 1
end
else
let
val w = g1ofg0 (atoi (args[1]))
and h = g1ofg0 (atoi (args[2]))
and num_particles = g1ofg0 (atoi (args[3]))
and seed = g1ofg0 (atoi (args[4]))
in
if (w < 1) + (h < 1) + (num_particles < 0) + (seed < 0) then
begin
fprintln! (stderr_ref, "Illegal command line argument.");
exit 1
end
else
let
val seed : uint = g0i2u seed
val () = srandom seed
val C = build_a_tree (w, h, num_particles)
in
write_a_PAM_image (stdout_ref, C, seed)
end
end
end
 
(*------------------------------------------------------------------*)
</syntaxhighlight>
 
=={{header|AutoHotkey}}==
Line 167 ⟶ 702:
Takes a little while to run, be patient.
Requires the [http://www.autohotkey.com/forum/topic32238.html GDI+ Standard Library by Tic]
<langsyntaxhighlight AHKlang="ahk">SetBatchLines -1
Process, Priority,, high
size := 400
Line 219 ⟶ 754:
Random, r, min, max
return r
}</langsyntaxhighlight>Sample output file [http://www.autohotkey.net/~crazyfirex/Images/brownian.png here]
 
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> SYS "SetWindowText", @hwnd%, "Brownian Tree"
SIZE = 400
Line 251 ⟶ 786:
UNTIL FALSE
</syntaxhighlight>
</lang>
[[File:Brownian_BBC.gif]]
 
=={{header|C}}==
{{libheader|FreeImage}}
<langsyntaxhighlight lang="c">#include <string.h>
#include <stdlib.h>
#include <time.h>
Line 320 ⟶ 854:
FreeImage_Save(FIF_BMP, img, "brownian_tree.bmp", 0);
FreeImage_Unload(img);
}</langsyntaxhighlight>
 
'''Bold text'''
Line 326 ⟶ 860:
{{trans|D}}
This version writes the image as Portable Bit Map to stdout and doesn't move already set particles.
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <time.h>
Line 368 ⟶ 902:
}
return 0;
}</langsyntaxhighlight>
Run-time about 12.4 seconds with SIDE=600, NUM_PARTICLES=10000.
 
=={{header|C sharp|C#}}==
{{works with|C#|3.0}}
{{libheader|System.Drawing}}
<langsyntaxhighlight lang="csharp">using System;
using System.Drawing;
 
Line 424 ⟶ 957:
}
}
}</langsyntaxhighlight>
 
=={{header|C++}}==
[[File:brownianTree_cpp.png|300px]]
 
For an animated version based on this same code see: [[Brownian tree/C++ animated]]
<langsyntaxhighlight lang="cpp">#include <windows.h>
#include <iostream>
#include <string>
Line 724 ⟶ 1,256:
return 0;
}
//--------------------------------------------------------------------</langsyntaxhighlight>
 
=={{header|Common Lisp}}==
When the random walk lands on a set pixel it sets the pixel at the previous position.
Line 731 ⟶ 1,262:
The former produces denser trees than the latter. If compiled with SBCL, providing a command line argument will invoke the latter method.
Requires Quicklisp library manager and the CL-GD package for producing PNG images.
<langsyntaxhighlight lang="lisp">;;; brownian.lisp
;;; sbcl compile: first load and then (sb-ext:save-lisp-and-die "brownian" :executable t :toplevel #'brownian::main)
(ql:quickload "cl-gd")
Line 816 ⟶ 1,347:
(write-image-to-file "brownian.png"
:compression-level 6 :if-exists :supersede)))
</langsyntaxhighlight>
 
=={{header|D}}==
Uses the module of the Grayscale Image task. Partial {{trans|PureBasic}}
<langsyntaxhighlight lang="d">void main() {
import core.stdc.stdio, std.random, grayscale_image;
 
Line 857 ⟶ 1,387:
data[] += 255;
Image!ubyte.fromData(data, side, side).savePGM("brownian_tree.pgm");
}</langsyntaxhighlight>
World side = 600, num_particles = 10_000, cropped (about 20 seconds run-time with dmd, about 4.3 seconds with ldc2):
<center>[[File:Dla_10000_d.png]]</center>
 
=={{header|Delphi}}==
<langsyntaxhighlight lang="delphi">const
SIZE = 256;
NUM_PARTICLES = 1000;
Line 915 ⟶ 1,444:
FreeAndNil(B);
end;
end;</langsyntaxhighlight>
 
=={{header|EasyLang}}==
 
[https://easylang.dev/show/#cod=dZHLboMwEEX3/oqzLoqxiahUCfIjiAUlRrVK7IjQFv6+snmkqpKFrfH1eM6dcet7PxxRaLTojaOrajKleAm7uPhvQ67IlRhMO6JkHpboKr3lkKCVqinRwlHyppQSPx+2N1gKnIDBXE0zCoCJkqFxZ+vG+PiAjvr8RP9yo+3pqnmHTQFYU5xihhSwwHR0EBmekmkpG8J5JSd3xJED2Qp+KNuOiQKFH5i3YOJURhdRXOKYDe+DaT5XvtwqPLC9eYQ42smTkgWb6QoO0/oz6EXqqtnfK/n/pWzoYT90WC7+jH6lZPMH7frTMiPBkuLin2/Xt96Y654un7QlhRS/ Run it]
[https://easylang.online/ide/?run=rect%20100%20100%0Acolor%20099%0Alen%20f%5B%5D%20200%2A200%0Amove%2050%2050%0Arect%200.5%200.5%0Af%5B100%2A200%2B100%5D%3D1%0An%3D9000%0Awhile%20i%20%3C%20n%0Ax%3Drandom%20200%0Ay%3Drandom%20200%0Awhile%20f%5By%2A200%2Bx%5D%3D1%0Ax%3Drandom%20200%0Ay%3Drandom%20200%0A.%0Awhile%20x%20%3C%3E%20-1%0Axo%3Dx%0Ayo%3Dy%0Ax%2B%3Drandom%203-1%0Ay%2B%3Drandom%203-1%0Aif%20x%20%3C%200%20or%20y%20%3C%200%20or%20x%20%3E%3D%20200%20or%20y%20%3E%3D%20200%0Ax%3D-1%0Aelse%0Aif%20f%5By%2A200%2Bx%5D%3D1%0Amove%20xo/2%20yo/2%0Arect%200.5%200.5%0Af%5Byo%2A200%2Bxo%5D%3D1%0Ai%2B%3D1%0Aif%20i%20mod%2016%3D0%0Acolor_red%200.2%2Bi/n%0Asleep%200%0A.%0Ax%3D-1%0A.%0A.%0A.%0A. Run it]
 
<syntaxhighlight>
<lang>rect 100 100
color3 0 1 1
color 099
len f[] 200 * 200
move 50 50
Line 929 ⟶ 1,457:
n = 9000
while i < n
repeat
x = random 200
y x = randomrandint 200 - 1
while f[ y *= randint 200 + x] =- 1
xuntil =f[y random* 200 + x + 1] <> 1
y = random 200
.
while x1 <>= -1
xo = x
yo = y
x += randomrandint 3 - 12
y += randomrandint 3 - 12
if x < 0 or y < 0 or x >= 200 or y >= 200
xbreak = -1
else.
if f[y * 200 + x + 1] = 1
move xo / 2 yo / 2
rect 0.5 0.5
f[yo * 200 + xo + 1] = 1
i += 1
if i mod 16 = 0
color_redcolor3 0.2 + i / n 1 1
sleep 0
.
x = -1
.
break 1
.
.
.
.</lang>
</syntaxhighlight>
 
=={{header|Evaldraw}}==
 
Based on the C version. Shows the brownian tree animate. Color each particle based on the time it settled. Dont overwrite existing particles.
 
[[File:Brownian tree from initial particle at center.gif|thumb|alt=Brownian trees form patterns similar to dendrites in nature|Animated brownian tree over the coarse of circa 1000 frames]]
 
<syntaxhighlight lang="c">
enum{SIZE=256, PARTICLES_PER_FRAME=10, PARTICLE_OK, GIVE_UP};
static world[SIZE][SIZE];
()
{
// set the seed
if (numframes==0) world[SIZE/2][SIZE/2] = 1;
t = klock();
simulate_brownian_tree(t);
 
cls(0);
for (y = 0; y < SIZE; y++){
for (x = 0; x < SIZE; x++){
cell = world[y][x];
if ( cell ) {
s = 100; // color scale
setcol(128+(s*cell % 128), 128+(s*.7*cell % 128), 128+(s*.1*cell % 128) );
setpix(x,y);
}
}
}
moveto(0,SIZE+15);
setcol(0xffffff);
printf("%g frames", numframes);
}
 
plop_particle(&px, &py) {
for (try=0; try<1000; try++) {
px = int(rnd*SIZE);
py = int(rnd*SIZE);
if (world[py][px] == 0) return PARTICLE_OK;
}
return GIVE_UP;
}
 
simulate_brownian_tree(time){
for(iter=0; iter<PARTICLES_PER_FRAME; iter++) // Rate of particle creation
{
// set particle's initial position
px=0; py=0;
if ( plop_particle(px,py) == GIVE_UP ) return;
 
while (1) { // Keep iterating until we bump into a solid particle
// randomly choose a direction
dx = int(rnd * 3) - 1;
dy = int(rnd * 3) - 1;
if (dx + px < 0 || dx + px >= SIZE || dy + py < 0 || dy + py >= SIZE)
{
// Restart if outside of screen
if ( plop_particle(px,py) == GIVE_UP ) return;
}else if (world[py + dy][px + dx]){
// bumped into something
world[py][px] = time;
break;
}else{
py += dy;
px += dx;
}
}
}
}
 
</syntaxhighlight>
 
=={{header|Factor}}==
This example sets four spawn points, one in each corner of the image, giving the result a vague x-shaped appearance. For visual reasons, movement is restricted to diagonals. So be careful if you change the seed or spawns — they should all fall on the same diagonal.
<lang factor>USINGheaderUSING: accessors images images.loader kernel literals math
math.vectors random sets ;
FROM: sets => in? ;
Line 1,007 ⟶ 1,606:
brownian-img "brownian.png" save-graphic-image ;
 
MAIN: save-brownian-tree-image</langsyntaxhighlight>
{{out}}
[https://i.imgur.com/qDVylB9.png image]
 
=={{header|Fantom}}==
 
<langsyntaxhighlight lang="fantom">
using fwt
using gfx
Line 1,115 ⟶ 1,713:
}
}
</syntaxhighlight>
</lang>
 
=={{header|Fortran}}==
{{works with|Fortran|95 and later}}
Line 1,124 ⟶ 1,721:
For RCImageBasic and RCImageIO, see [[Basic bitmap storage/Fortran]] and [[Write ppm file#Fortran]]
 
<langsyntaxhighlight lang="fortran">program BrownianTree
use RCImageBasic
use RCImageIO
Line 1,229 ⟶ 1,826:
end subroutine draw_brownian_tree
 
end program</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">' version 16-03-2017
' compile with: fbc -s gui
 
Line 1,291 ⟶ 1,887:
 
Beep : Sleep 5000
End</langsyntaxhighlight>
 
=={{header|Gnuplot}}==
{{Works with|gnuplot|5.0 (patchlevel 3) and above}}
Line 1,299 ⟶ 1,894:
'''plotff.gp''' - Plotting from any data-file with 2 columns (space delimited), and writing to png-file.<br>
Especially useful to plot colored fractals using points.
<langsyntaxhighlight lang="gnuplot">
## plotff.gp 11/27/16 aev
## Plotting from any data-file with 2 columns (space delimited), and writing to png-file.
Line 1,314 ⟶ 1,909:
plot dfn using 1:2 with points pt 7 ps 0.5 lc @clr
set output
</langsyntaxhighlight>
 
===Versions #1 - #4. Plotting from PARI/GP generated dat-files===
Line 1,325 ⟶ 1,920:
[[File:BT43gp.png|right|thumb|Output BT43gp.png]]
 
<langsyntaxhighlight lang="gnuplot">
## BTff.gp 11/27/16 aev
## Plotting 6 Brownian tree pictures.
Line 1,367 ⟶ 1,962:
ttl = "Brownian Tree v.#4-3"
load "plotff.gp"
</langsyntaxhighlight>
{{Output}}
<pre>
Line 1,374 ⟶ 1,969:
BT1gp.png, BT2gp.png, BT3gp.png, BT41gp.png, BT43gp.png, BT43gp.png.
</pre>
 
=={{header|Go}}==
[[file:GoTree.png|right|thumb|Output png]]
Line 1,380 ⟶ 1,974:
 
Using standard image library:
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,464 ⟶ 2,058:
}
return false
}</langsyntaxhighlight>
Nearly the same, version below works with code from the bitmap task:
<langsyntaxhighlight lang="go">package main
 
// Files required to build supporting package raster are found in:
Line 1,544 ⟶ 2,138:
}
return false
}</langsyntaxhighlight>
 
=={{header|Haskell}}==
 
The modules <code>[[Bitmap#Haskell|Bitmap]]</code>, <code>[[Bitmap/Write a PPM file#Haskell|Bitmap.Netpbm]]</code>, and <code>[[Bitmap/Histogram#Haskell|Bitmap.BW]]</code> are on Rosetta Code. The commented-out type signatures require [http://hackage.haskell.org/trac/haskell-prime/wiki/ScopedTypeVariables scoped type variables] in order to function.
 
<langsyntaxhighlight lang="haskell">import Control.Monad
import Control.Monad.ST
import Data.STRef
Line 1,595 ⟶ 2,188:
liftM2 (,) [1 .. width - 2] [0, height - 1]
off = black
on = white</langsyntaxhighlight>
 
=={{header|Icon}} and {{header|Unicon}}==
[[File:Brownian_tree_unicon.png|400px|thumb|right|400x400 PA=70% SA=50% D=8%]]
In this version the seed is randomly set within an inner area and particles are injected in an outer ring.
 
<langsyntaxhighlight Iconlang="icon">link graphics,printf
 
procedure main() # brownian tree
Line 1,666 ⟶ 2,258:
pt +:= ( pt > (1-core)/2, core)
return pt
end</langsyntaxhighlight>
 
{{libheader|Icon Programming Library}}
[http://www.cs.arizona.edu/icon/library/src/procs/graphics.icn graphics.icn provides graphics]
[http://www.cs.arizona.edu/icon/library/src/procs/printf.icn printf.icn provides printf]
 
=={{header|J}}==
 
<langsyntaxhighlight lang="j">brtr=:4 :0
seed=. ?x
clip=. 0 >. (<:x) <."1 ]
Line 1,692 ⟶ 2,283:
end.
field
)</langsyntaxhighlight>
 
Example use:
 
<langsyntaxhighlight lang="j"> require'viewmat'
viewmat 480 640 brtr 30000</langsyntaxhighlight>
 
Note that building a brownian tree like this takes a while and would be more interesting if this were animated.
 
=={{header|Java}}==
{{libheader|Swing}} {{libheader|AWT}}
<langsyntaxhighlight lang="java">import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.*;
Line 1,774 ⟶ 2,364:
}
}
}</langsyntaxhighlight>
 
This is an alternate version which is a port of most of the code here.
This code does not use a GUI and saves the output to image.png.
<langsyntaxhighlight Javalang="java">import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.File;
Line 1,867 ⟶ 2,457:
}
}
}</langsyntaxhighlight>
=={{header|JavaScript}}==
 
=={{header|JavaScript}}=Using + &lt;canvas>===
[http://switchb.org/kpreid/2010/brownian-tree/ Live version] <!-- If changing this example, add note this link is outdated -->
<langsyntaxhighlight lang="javascript">function brownian(canvasId, messageId) {
var canvas = document.getElementById(canvasId);
var ctx = canvas.getContext("2d");
Line 1,999 ⟶ 2,589:
}, 1);
 
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="html"><html>
<head>
<script src="brownian.js"></script>
Line 2,009 ⟶ 2,599:
<div id="message"></div>
</body>
</html></langsyntaxhighlight>
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
This solution puts the seed in the center of the canvas. Motes are generated randomly in space and do a simple drunkard's walk until they hit the tree or leave the canvas (unless the sides are made <tt>side</tt>). The Motes are colorized according to their &theta; in polar coordinates.
 
<langsyntaxhighlight lang="julia">using Images, FileIO
 
function main(h::Integer, w::Integer, side::Bool=false)
Line 2,056 ⟶ 2,645:
imgwtside = main(256, 256, true)
save("data/browniantree_noside.jpg", imgnoside)
save("data/browniantree_wtside.jpg", imgwtside)</langsyntaxhighlight>
 
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">// version 1.1.2
 
import java.awt.Graphics
Line 2,123 ⟶ 2,711:
b.isVisible = true
Thread(b).start()
}</langsyntaxhighlight>
 
=={{header|Liberty BASIC}}==
<langsyntaxhighlight lang="lb">'[RC]Brownian motion tree
nomainwin
dim screen(600,600)
Line 2,208 ⟶ 2,795:
timer 0
close #1
end</langsyntaxhighlight>
=={{header|Locomotive Basic}}==
 
{{trans|ZX Spectrum Basic}}
This program is ideally run in [https://benchmarko.github.io/CPCBasic/cpcbasic.html CPCBasic] and should finish after about 20 to 25 minutes (Chrome, desktop CPU). At normal CPC speed, it would probably take several days to run when set to 10000 particles.
<syntaxhighlight lang="locobasic">10 MODE 1:DEFINT a-z:RANDOMIZE TIME:np=10000
20 INK 0,0:INK 1,26:BORDER 0
30 PLOT 320,200
40 FOR i=1 TO np
50 GOSUB 1000
60 IF TEST(x+1,y+1)+TEST(x,y+1)+TEST(x+1,y)+TEST(x-1,y-1)+TEST(x-1,y)+TEST(x,y-1)<>0 THEN 100
70 x=x+RND*2-1: y=y+RND*2-1
80 IF x<1 OR x>640 OR y<1 OR y>400 THEN GOSUB 1000
90 GOTO 60
100 PLOT x,y
110 NEXT
120 END
1000 ' Calculate new position
1010 x=RND*640
1020 y=RND*400
1030 RETURN</syntaxhighlight>
=={{header|Lua}}==
The output is stored in as a ppm-image. The source code of these output-functions is located at
Line 2,215 ⟶ 2,820:
[[Grayscale image#Lua]],
[[Basic bitmap storage#Lua]].
<langsyntaxhighlight lang="lua">function SetSeed( f )
for i = 1, #f[1] do -- the whole boundary of the scene is used as the seed
f[1][i] = 1
Line 2,281 ⟶ 2,886:
end
end
Write_PPM( "brownian_tree.ppm", ConvertToColorImage(f) )</langsyntaxhighlight>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
 
=={{header|Mathematica}}==
There is a [http://demonstrations.wolfram.com/DiffusionLimitedAggregation/ prettier version] at the Mathematica demo site. Its source code is also available there but it is not mine.
 
Loose {{trans|D}}
<langsyntaxhighlight Mathematicalang="mathematica">canvasdim = 1000;
n = 0.35*canvasdim^2;
canvas = ConstantArray[0, {canvasdim, canvasdim}];
Line 2,312 ⟶ 2,916:
{i, (particle + ds), MatrixPlot@canvas}
]
MatrixPlot[canvas,FrameTicks->None,ColorFunction->"DarkRainbow",ColorRules->{0 -> None}]</langsyntaxhighlight>
 
Result:
 
[[File:BrownianTree.png]]
=={{header|Nim}}==
{{libheader|imageman}}
 
<syntaxhighlight lang="nim">import random
import imageman
 
const
Size = 400 # Area size.
MaxXY = Size - 1 # Maximum possible value for x and y.
NPart = 25_000 # Number of particles.
Background = ColorRGBU [byte 0, 0, 0] # Background color.
Foreground = ColorRGBU [byte 50, 150, 255] # Foreground color.
 
randomize()
var image = initImage[ColorRGBU](Size, Size)
image.fill(Background)
image[Size div 2, Size div 2] = Foreground
 
for _ in 1..NPart:
 
block ProcessParticle:
while true: # Repeat until the particle is freezed.
 
# Choose position of particle.
var x, y = rand(MaxXY)
if image[x, y] == Foreground:
continue # Not free. Try again.
 
# Move the particle.
while true:
 
# Choose a motion.
let dx, dy = rand(-1..1)
inc x, dx
inc y, dy
if x notin 0..MaxXY or y notin 0..MaxXY:
break # Out of limits. Try again.
 
# Valid move.
if image[x, y] == Foreground:
# Not free. Freeze the particle at its previous position.
image[x - dx, y - dy] = Foreground
break ProcessParticle # Done. Process next particle.
 
# Save into a PNG file.
image.savePNG("brownian.png", compression = 9)</syntaxhighlight>
=={{header|OCaml}}==
{{trans|D}}
 
<langsyntaxhighlight lang="ocaml">let world_width = 400
let world_height = 400
let num_particles = 20_000
Line 2,368 ⟶ 3,017:
dla ~world;
to_pbm ~world;
;;</langsyntaxhighlight>
 
better to compile to native code to get a faster program:
Line 2,374 ⟶ 3,023:
<pre>$ ocamlopt -o brownian_tree.opt brownian_tree.ml
$ ./brownian_tree.opt | display -</pre>
 
=={{header|Octave}}==
{{trans|C}}
 
<langsyntaxhighlight lang="octave">function r = browniantree(xsize, ysize = xsize, numparticle = 1000)
r = zeros(xsize, ysize, "uint8");
r(unidrnd(xsize), unidrnd(ysize)) = 1;
Line 2,404 ⟶ 3,052:
r = browniantree(200);
r( r > 0 ) = 255;
jpgwrite("browniantree.jpg", r, 100); % image package</langsyntaxhighlight>
 
=={{header|PARI/GP}}==
All versions #1 - #4 are based on using 4 small plotting helper functions, which are allowing to unify
Line 2,413 ⟶ 3,060:
 
===Plotting helper functions===
<langsyntaxhighlight lang="parigp">
\\ 2 old plotting helper functions 3/2/16 aev
\\ insm(): Check if x,y are inside matrix mat (+/- p deep).
Line 2,442 ⟶ 3,089:
plothraw(Vec(vx),Vec(vy));
}
</langsyntaxhighlight>
===Version #1. Translated from AutoHotkey.===
{{trans|AutoHotkey}}
[[File:BTAH1.png|right|thumb|Output BTAH1.png]]
 
<langsyntaxhighlight lang="parigp">
\\ Brownian tree v.#1. Translated from AutoHotkey
\\ 3/8/2016, upgraded 11/27/16 aev
Line 2,474 ⟶ 3,121:
{BrownianTree1(400,15000,"c:\\pariData\\BTAH1.dat");
plotff("c:\\pariData\\BTAH1.dat");} \\BTAH1.png
</langsyntaxhighlight>
 
{{Output}}
Line 2,493 ⟶ 3,140:
[[File:BTOC1.png|right|thumb|Output BTOC1.png]]
 
<langsyntaxhighlight lang="parigp">
\\ Brownian tree v.#2. Translated from Octave
\\ 3/8/2016, upgraded 11/27/16 aev
Line 2,518 ⟶ 3,165:
{BrownianTree2(1000,3000,"c:\\pariData\\BTOC1.dat");
plotff("c:\\pariData\\BTOC1.dat");} \\BTOC1.png
</langsyntaxhighlight>
 
{{Output}}
Line 2,536 ⟶ 3,183:
[[File:BTSE1.png|right|thumb|Output BTSE1.png]]
 
<langsyntaxhighlight lang="parigp">
\\ Brownian tree v.#3. Translated from Seed7
\\ 3/8/2016, upgraded 11/27/16 aev
Line 2,563 ⟶ 3,210:
{BrownianTree3(400,5000,"c:\\pariData\\BTSE1.dat");
plotff("c:\\pariData\\BTSE1.dat");} \\BTSE1.png
</langsyntaxhighlight>
 
{{Output}}
Line 2,583 ⟶ 3,230:
[[File:BTPB3.png|right|thumb|Output BTPB3.png]]
 
<langsyntaxhighlight lang="parigp">
\\ Brownian tree v.#4. Translated from PureBasic
\\ 3/8/2016, upgraded 11/27/16 aev
Line 2,623 ⟶ 3,270:
{BrownianTree4(200,4000,"c:\\pariData\\BTPB3.dat",2,5);
plotff("c:\\pariData\\BTPB3.dat");} \\BTPB3.png
</langsyntaxhighlight>
 
{{Output}}
Line 2,654 ⟶ 3,301:
*** Plotting from: c:\pariData\BTPB3.dat - 3641 DOTS
</pre>
 
=={{header|Perl}}==
[[File:brownian-00.png|thumb]][[File:brownian-05.png|thumb]][[File:brownian-11.png|thumb]]
Line 2,660 ⟶ 3,306:
 
Code runs until the tree reached specified radius. Output is written to "test.eps" of wherever the current directory is.
<syntaxhighlight lang="perl">use strict;
<lang perl>sub PI() { atan2(1,1) * 4 } # The, er, pi
use warnings;
sub STEP() { .5 } # How far does the particle move each step. Affects
 
# both speed and accuracy greatly
use constant PI => 2*atan2(1,0); # π
sub STOP_RADIUS() { 100 } # When the tree reaches this far from center, end
use constant STEP => 0.5; # How far particle moves each step. Affects both speed and accuracy greatly
use constant STOP_RADIUS => 100; # When the tree reaches this far from center, end
 
# At each step, move this much towards center. Bigger numbers help the speed because
# particles are less likely to wander off, but greatly affects tree shape.
# Should be between 0 and 1 ish. Set to 0 for pain.
subuse constant ATTRACT() {=> 0.2 };
 
my @particles = map([ map([], 0 .. 2 * STOP_RADIUS) ], 0 .. 2 * STOP_RADIUS);
push @{ $particles[STOP_RADIUS][STOP_RADIUS] }, [0, 0];
my($r_start, $max_dist) = (3, 0);
 
my $r_start = 3;
my $max_dist = 0;
 
sub dist2 {
no warnings 'uninitialized';
my ($dx, $dy) = ($_[0][0] - $_[1][0], $_[0][1] - $_[1][1]);
$dx * $dx + $dy * $dy
Line 2,760 ⟶ 3,407:
 
my $count;
PARTICLE: while (1) {
my $a = rand(2 * PI);
my $p = [ $r_start * cos($a), $r_start * sin($a) ];
while (my $m = move( $p)) {
if ($m == 1) { next }
elsif ($m == 2) { $count++; last; }
elsif ($m == 3) { last PARTICLE }
else { last }
}
print STDERR "$count $max_dist/@{[int($r_start)]}/@{[STOP_RADIUS]}\r" unless $count% 7;
Line 2,774 ⟶ 3,421:
sub write_eps {
my $size = 128;
my $p = $size / (STOP_RADIUS * 1.05);
my $b = STOP_RADIUS * $p;
if ($p < 1) {
$size = STOP_RADIUS * 1.05;
$bp = STOP_RADIUS1;
$pb = 1STOP_RADIUS;
}
 
my $hp = $p / 2;
 
open OUT, "'>"', "'test.eps"';
print OUT <<~"HEAD";
 
# print EPS to standard%!PS-Adobe-3.0 outEPSF-3.0
%%BoundingBox: 0 0 @{[$size*2, $size*2]}
print OUT <<"HEAD";
$size $size translate
%!PS-Adobe-3.0 EPSF-3.0
/l{ rlineto }def
%%BoundingBox: 0 0 @{[$size*2, $size*2]}
/c{ $hp 0 360 arc fill }def
$size $size translate
-$size -$size moveto
/l{ rlineto }def
$size 2 mul 0 l
/c{ $hp 0 360 arc fill }def
-$size - 0 $size moveto2 mul l
-$size 2 mul 0 l
closepath
0 $size 2 mul l
0 setgray fill
-$size 2 mul 0 l
0 setlinewidth .1 setgray 0 0 $b 0 360 arc stroke
closepath
.8 setgray /TimesRoman findfont 16 scalefont setfont
0 setgray fill
-$size 10 add $size -16 add moveto
0 setlinewidth .1 setgray 0 0 $b 0 360 arc stroke
(Step = @{[STEP]} Attract = @{[ATTRACT]}) show
.8 setgray /TimesRoman findfont 16 scalefont setfont
0 1 0 setrgbcolor newpath
-$size 10 add $size -16 add moveto
HEAD
(Step = @{[STEP]} Attract = @{[ATTRACT]}) show
0 1 0 setrgbcolor newpath
HEAD
 
for (@particles) {
Line 2,815 ⟶ 3,459:
}
 
write_eps();</langsyntaxhighlight>
 
=={{header|Phix}}==
As-is, runs in about 2s, but can be very slow when bigger or (even worse) resize-able.
{{libheader|Phix/pGUI}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>--
<span style="color: #000080;font-style:italic;">-- demo\rosetta\BrownianTree.exw</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
--
include pGUI.e
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">canvas</span>
 
<span style="color: #004080;">cdCanvas</span> <span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span>
Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas
<span style="color: #008080;">function</span> <span style="color: #000000;">redraw_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000080;font-style:italic;">/*posx*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000080;font-style:italic;">/*posy*/</span><span style="color: #0000FF;">)</span>
 
<span style="color: #004080;">integer</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ox</span><span style="color: #0000FF;">,</span><span style="color: #000000;">oy</span>
function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/)
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">width</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">height</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetIntInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"DRAWSIZE"</span><span style="color: #0000FF;">)</span>
integer x,y,ox,oy
<span style="color: #004080;">sequence</span> <span style="color: #000000;">grid</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">),</span><span style="color: #000000;">height</span><span style="color: #0000FF;">)</span>
integer {width, height} = IupGetIntInt(canvas, "DRAWSIZE")
<span style="color: #004080;">integer</span> <span style="color: #000000;">xy</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">width</span><span style="color: #0000FF;">*</span><span style="color: #000000;">height</span><span style="color: #0000FF;">*</span><span style="color: #000000;">0.8</span><span style="color: #0000FF;">)</span>
sequence grid = repeat(repeat(0,width),height)
<span style="color: #000080;font-style:italic;">--atom t = time()+1</span>
integer xy = floor(width*height*0.8)
<span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">width</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)][</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">height</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
--atom t = time()+1
<span style="color: #7060A8;">cdCanvasActivate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
grid[floor(width/2)][floor(height/2)] = 1
<span style="color: #7060A8;">cdCanvasClear</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
cdCanvasActivate(cddbuffer)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">xy</span> <span style="color: #008080;">do</span>
cdCanvasClear(cddbuffer)
<span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">width</span><span style="color: #0000FF;">)</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">height</span><span style="color: #0000FF;">)</span>
for i=1 to xy do
<span style="color: #000000;">ox</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span> <span style="color: #000000;">oy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span>
x = rand(width) y = rand(height)
<span style="color: #008080;">while</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">x</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">width</span>
ox = x oy = y
<span style="color: #008080;">and</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">y</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">height</span> <span style="color: #008080;">do</span>
while x>=1 and x<=width
<span style="color: #008080;">if</span> <span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
and y>=1 and y<=height do
<span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">oy</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ox</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
if grid[y][x] then
<span style="color: #7060A8;">cdCanvasPixel</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ox</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">oy</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">#00FF00</span><span style="color: #0000FF;">)</span>
grid[oy][ox] = 1
cdCanvasPixel(cddbuffer, ox,<span oy,style="color: #00FF00) 008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
exit
<span style="color: #000000;">ox</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">2</span>
end if
<span style="color: #000000;">oy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">2</span>
ox = x x += rand(3)-2
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
oy = y y += rand(3)-2
<span style="color: #000080;font-style:italic;">-- -- if making the canvas bigger/resizeable,
end while
-- -- if makingput thethis canvasin bigger/resizeable,so that you can kill it.
-- if time()&gt;=t then
-- -- put this in so that you can kill it.
-- if time()>=t then ?{i,xy}
-- ?{i,xy}t = time()+1
-- end t = time()+1if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
-- end if
<span style="color: #7060A8;">cdCanvasFlush</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
cdCanvasFlush(cddbuffer)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
return IUP_DEFAULT
end function
<span style="color: #008080;">function</span> <span style="color: #000000;">map_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
 
<span style="color: #000000;">cdcanvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_IUP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
function map_cb(Ihandle ih)
<span style="color: #000000;">cddbuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_DBUFFER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">)</span>
cdcanvas = cdCreateCanvas(CD_IUP, ih)
<span style="color: #7060A8;">cdCanvasSetBackground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_WHITE</span><span style="color: #0000FF;">)</span>
cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
<span style="color: #7060A8;">cdCanvasSetForeground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_RED</span><span style="color: #0000FF;">)</span>
cdCanvasSetBackground(cddbuffer, CD_WHITE)
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
cdCanvasSetForeground(cddbuffer, CD_RED)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
return IUP_DEFAULT
end function
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span>
 
function esc_close(Ihandle /*ih*/, atom c)
<span style="color: #000000;">canvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span>
if c=K_ESC then return IUP_CLOSE end if
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"RASTERSIZE"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"200x200"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- fixed size</span>
return IUP_CONTINUE
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"MAP_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"map_cb"</span><span style="color: #0000FF;">))</span>
end function
 
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"RESIZE=NO"</span><span style="color: #0000FF;">)</span>
procedure main()
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Brownian Tree"</span><span style="color: #0000FF;">)</span>
IupOpen()
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"ACTION"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"redraw_cb"</span><span style="color: #0000FF;">))</span>
 
canvas = IupCanvas(NULL)
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
IupSetAttribute(canvas, "RASTERSIZE", "200x200") -- fixed size
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span>
 
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span>
dlg = IupDialog(canvas, "RESIZE=NO")
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
IupSetAttribute(dlg, "TITLE", "Brownian Tree")
<!--</syntaxhighlight>-->
IupSetCallback(dlg, "K_ANY", Icallback("esc_close"))
IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))
 
IupMap(dlg)
IupShowXY(dlg,IUP_CENTER,IUP_CENTER)
IupMainLoop()
IupClose()
end procedure
 
main()</lang>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/simul.l")
 
(de brownianTree (File Size Cnt)
Line 2,913 ⟶ 3,547:
(for This L
(prin (if (: pix) 1 0)) )
(prinl) ) ) ) )</langsyntaxhighlight>
Use:
<pre>(brownianTree "img.pbm" 300 9000)
(call 'display "img.pbm")</pre>
 
=={{header|Processing}}==
<langsyntaxhighlight lang="java">boolean SIDESTICK = false;
boolean[][] isTaken;
 
Line 2,954 ⟶ 3,587:
}
}
if (frameCount > width * height) noLoop();{
noLoop();
}</lang>
}
}</syntaxhighlight>
 
==={{header|Processing Python mode}}===
Line 2,961 ⟶ 3,596:
{{trans|Processing}}
 
<langsyntaxhighlight lang="python">SIDESTICK = False
 
def setup() :
Line 2,991 ⟶ 3,626:
if frameCount > width * height:
noLoop()</langsyntaxhighlight>
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">#Window1 = 0
#Image1 = 0
#ImgGadget = 0
Line 3,032 ⟶ 3,666:
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf</langsyntaxhighlight>[[File:BrownianTree.pb.png]]
 
=={{header|Python}}==
{{libheader|pygame}}
<langsyntaxhighlight lang="python">import pygame, sys, os
from pygame.locals import *
from random import randint
Line 3,136 ⟶ 3,769:
while True:
input(pygame.event.get())
pygame.display.flip()</langsyntaxhighlight>
 
=={{header|R}}==
All versions #1 - #4 are based on using 2 small plotting helper functions, which are allowing to unify
Line 3,160 ⟶ 3,792:
file could be very slow too. Actually, plotv2() shows almost "pure" plotting time.
 
<syntaxhighlight lang="r">
<lang r>
# plotmat(): Simple plotting using a square matrix mat (filled with 0/1). v. 8/31/16
# Where: mat - matrix; fn - file name; clr - color; ttl - plot title;
Line 3,200 ⟶ 3,832:
cat(" *** END:", date(), "\n");
}
</langsyntaxhighlight>
 
===Versions #1- #4.===
Line 3,208 ⟶ 3,840:
 
====Version #1.====
<syntaxhighlight lang="r">
<lang r>
# Generate and plot Brownian tree. Version #1.
# 7/27/16 aev
Line 3,242 ⟶ 3,874:
}
gpBrownianTree1(400,15000,"red", "BT1R", "Brownian Tree v.1", 1);
</langsyntaxhighlight>
 
{{Output}}
Line 3,255 ⟶ 3,887:
 
====Version #2.====
<syntaxhighlight lang="r">
<lang r>
# Generate and plot Brownian tree. Version #2.
# 7/27/16 aev
Line 3,293 ⟶ 3,925:
## Rename BT2R.dmp to BT2aR.dmp
plotv2("BT2aR", "orange", "Brownian Tree v.2a", 640)
</langsyntaxhighlight>
 
{{Output}}
Line 3,314 ⟶ 3,946:
 
====Version #3.====
<syntaxhighlight lang="r">
<lang r>
# Generate and plot Brownian tree. Version #3.
# 7/27/16 aev
Line 3,354 ⟶ 3,986:
}
gpBrownianTree3(400,5000,"dark green", "BT3R", "Brownian Tree v.3", 1);
</langsyntaxhighlight>
 
{{Output}}
Line 3,368 ⟶ 4,000:
 
====Version #4.====
<syntaxhighlight lang="r">
<lang r>
# Generate and plot Brownian tree. Version #4.
# 7/27/16 aev
Line 3,410 ⟶ 4,042:
}
gpBrownianTree4(400,15000,"navy", "BT4R", "Brownian Tree v.4", 1);
</langsyntaxhighlight>
 
{{Output}}
Line 3,422 ⟶ 4,054:
*** END: Mon Sep 05 11:50:47 2016
</pre>
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">#lang racket
(require 2htdp/image)
 
Line 3,547 ⟶ 4,178:
 
img
(save-image img "brownian-tree.png")</langsyntaxhighlight>
 
=={{header|Raku}}==
(formerly Perl 6)
Line 3,558 ⟶ 4,188:
{{works with|Rakudo|2015.12}}
 
<syntaxhighlight lang="raku" perl6line>constant size = 100;
constant particlenum = 1_000;
 
Line 3,624 ⟶ 4,254:
}
 
display;</langsyntaxhighlight>
 
=={{header|REXX}}==
A large part of the REXX program's prologue was to handle the various options. <br>
Line 3,631 ⟶ 4,260:
With a little more REXX code, a &nbsp; ''petri dish'' &nbsp; option could be added, that is, when a particle hits the edge, <br>
it "bounces" back. &nbsp; Also, the field could then be displayed as a round area &nbsp; (like a petri dish).
 
REXX code was added to display snapshots of the field, either after so many cycles, and/or after some <br>
elapsed time has elapsed (whole seconds only). &nbsp; This makes for some fascinating observations.
 
Program note: &nbsp; to keep things simple, the (system) command to clear the screen was hard-coded as &nbsp; '''CLS'''.
<langsyntaxhighlight lang="rexx">/*REXX program animates and displays Brownian motion of dust in a field (with one seed).*/
mote = '·' /*character for a loose mote (of dust).*/
hole = ' ' /* " " an empty spot in field.*/
clearScr = 'CLS' /*(DOS) command to clear the screen. */
eons = 1000000 /*number cycles for Brownian movement.*/
snapshot = 0 /*every N winks, display a snapshot.*/
snaptime = 1 /* " " secs, " " " */
seedPos = 30 45 /*place a seed in this field position. */
seedPos = 0 /*if =0, then use middle of the field.*/
/* " -1, " " a random placement.*/
/*otherwise, place the seed at seedPos.*/
/*use RANDSEED for RANDOM repeatability*/
parse arg heightsd widthsw motes tree randSeed . /*obtain optional arguments from the CL*/
if height sd=='' | heightsd=="," then heightsd= 0 /*Not specified? Then use the default.*/
if width sw=='' | widthsw=="," then width then sw= 0 /* " " " " " " */
if motes=='' | motes=="," then motes= '1018%' /*The % dust motes in the field, */
/* [↑] either a # -or-─or─ a # with a %.*/
if tree=='' | tree==mote then tree=' "*'" /*the character used to show the tree. */
if length(tree)==2 then tree=x2c(tree) /*tree character was specified in hex. */
if datatype(randSeed,'W') then call random ,,randSeed /*if an integer, use the seed.*/
/* [↑] set the first random number. */
if heightsd==0 | widthsw==0 then _= scrsize() /*Note: not all REXXes have SCRSIZE BIF*/
if heightsd==0 then heightsd= word(_, 1) -3 2 /*adjust useableusable depth height for the border.*/
if sw==0 width==0 then widthsw= word(_, 2) - 1 /* " " width " " " */
seedAt= seedPos /*assume a seed position (initial pos).*/
if seedPos== 0 then seedAt=width%2 height(sw % 2) (sd % 2) /*if it's a zero, start in the middle.*/
if seedPos==-1 then seedAt= random(1, widthsw) random(1,heightsd) /*if negative, use random.*/
parse var seedAt xs ys . /*obtain the X and Y seed coördinates*/
/* [↓] if right-mostright─most ≡ '%', then use %*/
if right(motes, 1) == '%' then motes=height sd * widthsw * strip(motes, , '%') % 100
@.=hole hole /*create the Brownian field, all empty.*/
do j=1 for motes /*sprinkle a # of dust motes randomly.*/
 
rx= random(1, sw); ry= random(1, sd); @.rx.ry= mote
do j=1 for motes /*sprinkle a # of dust motes randomly.*/
rx=random(1, width); end ry=random(1,/*j*/ height); @.rx.ry= /* [↑] place a mote at random in field*/
end /*j*/ /*plant [↑]a seed placefrom awhich motethe attree randomwill ingrow fieldfrom*/
@.xs.ys= tree /*plantdust themotes seedthat fromaffix whichthemselves to the tree . */
call show; loX= 1; hiX= sw /*show field before we mess it will grow from dust motes thatup again*/
@.xs.ys=tree loY= 1; hiY= sd /*used to optimize the mote affixed themselves to otherssearching. */
call show /*show field before we mess it up again*/
tim=0 /*the time in seconds of last display. */
loX=1; hiX= width /*used to optimize the mote searching.*/
loY=1; hiY=height /* " " " " " " */
/*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ soooo, this is Brownian motion.*/
do winksBrownian=1 for eons until \motion; call show /*EONsshow isBrownion usedmotion insteaduntil ofno ∞; close 'nufmotion.*/
motionminx=0 loX; maxX= hiX; loX= sw; hiX= 1 /*turn offas the tree Browniangrows, motionthe search flag.for the*/
minY= loY; maxY= hiY; loY= sd; hiy= 1 /*dust motes gets faster due to croping*/
if snapshot\==0 then if winks//snapshot==0 then call show
call BM /*invoke the Brownian movement routine.*/
if snaptime\==0 then do; t=time('S')
if loX>1 & hiX<sw & loY>1 & hiY<sd then iterate /*Need cropping? No, then keep moving*/
if t\==tim & t//snaptime==0 then do; tim=t; call show
call crop /*delete motes (moved off petri endfield).*/
end /*Brownian*/ /*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*/
end
exit 0 minX=loX; maxX=hiX /*asstick thea treefork grows,in the searchit, for we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
minY=loY; maxY=hiY /* dust motes gets faster. */
crop: loX= width; do hiXyc=-1 to sd+1 by sd+2; do xc=-1 to sw+1; @.xc.yc= hole; end /*used to limit the mote searching. xc*/
loY=height; hiY=1 end /* " " " " " " yc*/
do xc=-1 to sw+1 by sw+2; do yc=-1 to sd+1; @.xc.yc= hole; end /*yc*/
 
do x =minXend to maxX /*xc*/; xm=x-1; xp=x+1 /*a couple handy-dandy values*/ return
/*──────────────────────────────────────────────────────────────────────────────────────*/
do y=minY to maxY; if @.x.y\==mote then iterate /*Not a mote: keep looking. */
show: 'CLS'; motion= if0; x<loX thendo loX=x; if x>hiX then hiXys=xsd for sd by -1; /*faster than: hiXaRow=max(X,hiX)*/
if y<loY then loY=y; if y>hiY then hiY do xs=y1 for sw; /*faster than: hiY aRow=max(y,hiY)*/ aRow || @.xs.ys
if @.xm.y ==tree then do; @.x.y=tree; iterate; end /*there a neighbor of tree? end /*xs*/
if @.xp.y ==tree then do; @.x.y=tree; iterate; end /*there a neighbor of tree? */ say aRow
end /*ys*/; return
ym=y-1
/*──────────────────────────────────────────────────────────────────────────────────────*/
if @.x.ym ==tree then do; @.x.y=tree; iterate; end /*there a neighbor of tree? */
BM: do x =minX to maxX; if @.xm.ym==tree x then- do1; @.x.y xp=tree; iterate;x + 1 end /*theretwo ahandy─dandy neighbor ofvalues. tree? */
ifdo @.xp.ym=y=treeminY thento domaxY; if @.x.y\=tree;=mote iterate; endthen iterate /*thereNot a neighbormote: of tree? keep looking.*/
if x<loX then loX=x; if x>hiX then hiX= x /*faster than hiX=max(X,hiX)*/
yp=y+1
if @.x.yp ==treey<loY then doloY=y; @.x. if y>hiY then hiY=tree; iterate;y end /*there a neighbor of" tree? " hiY=max(y,hiY)*/
if @.xm.ypy ==tree then do; @.x.y= tree; iterate; end /*there a neighbor of tree? */
if @.xp.ypy ==tree then do; @.x.y= tree; iterate; end /*there a neighbor" of tree? " " " " */
ym= y - 1
motion=1 /* [↓] Brownian motion is coming. */
xb=if @.x.ym +==tree random(1, 3)then do; -@.x.y= 2tree; iterate; end /* " " " /*" apply Brownian motion for X." */
ybif @.xm.ym=y + random(1, 3) - 2 =tree then do; @.x.y= tree; iterate; end /* " " " " " Y. */
if @.xp.ym==tree then do; @.x.y= tree; iterate; end /* " " " " " */
yp = y + 1
if @.x.yp ==tree then do; @.x.y= tree; iterate; end /* " " " " " */
if @.xm.yp==tree then do; @.x.y= tree; iterate; end /* " " " " " */
if @.xp.yp==tree then do; @.x.y= tree; iterate; end /* " " " " " */
motion= 1 /* [↓] Brownian motion is coming. */
xb= x + random(1, 3) - 2 /* apply Brownian motion for X. */
yb= y + random(1, 3) - 2 /* " " " " Y. */
if @.xb.yb\==hole then iterate /*can the mote actually move to there ?*/
@.x.y=hole hole /*"empty out" the old mote position. */
@.xb.yb=mote mote /*move the mote (or possibly not). */
if xb<loX then loX= max(1, xb); if xb>hiX then hiX= min( widthsw, xb)
if yb<loY then loY= max(1, yb); if yb>hiY then hiY= min(heightsd, yb)
end /*y*/ /* [↑] limit mote's movement to field.*/
end /*x*/; return</syntaxhighlight>
This REXX program makes use of &nbsp; '''scrsize''' &nbsp; REXX program (or BIF) which is used to determine the screen size of the terminal (console).
 
The &nbsp; '''SCRSIZE.REX''' &nbsp; REXX program is included at &nbsp; ───► &nbsp; [[SCRSIZE.REX]].
call crop /*crops (or truncates) the mote field.*/
end /*winks*/ /*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*/
 
{{out|final output|text=&nbsp; when using the following inputs (screen size was 160&times;160): &nbsp; &nbsp; <tt> , &nbsp; , &nbsp; , &nbsp; fe </tt>}}
call show
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
crop: if loX>1 & hiX<width & loY>1 & hiY<height then return /*are we cropping?*/
/* [↓] delete motes (moved off field).*/
do yc=-1 to height+1 by height+2
do xc=-1 to width+1; if @.xc.yc==hole then iterate; @.xc.yc=hole
end /*xc*/
end /*yc*/
/* [↓] delete motes (moved off field).*/
do xc=-1 to width+1 by width+2
do yc=-1 to height+1; if @.xc.yc==hole then iterate; @.xc.yc=hole
end /*yc*/
end /*xc*/
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
show: clearScr /*¬ necessary, but everything speeds up*/
do ys=height for height by -1; aRow=
do xs=1 for width; aRow=aRow || @.xs.ys
end /*xs*/
say aRow
end /*ys*/
return</lang>
This REXX program makes use of '''scrsize''' REXX program (or BIF) which is used to determine the screen size of the terminal (console).
 
(Shown at one─sixth size.)
The '''SCRSIZE.REX''' REXX program is included at [[SCRSIZE.REX]].
 
Final output when using the following inputs (screen size was 160&times;160): &nbsp; &nbsp; <tt> , &nbsp; , &nbsp; , &nbsp; fe </tt>
(Shown at one-sixthth size.)
<pre style="font-size:17%;font-weight:bold;">
Line 3,861 ⟶ 4,460:
</pre>
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Brownian tree
 
Line 3,962 ⟶ 4,560:
next
return number(str)
</syntaxhighlight>
</lang>
Output:
 
[https://www.dropbox.com/s/a22tu6wf0ibu502/BrownianTree.jpg?dl=0 Brownian tree]
 
=={{header|Ruby}}==
{{libheader|RMagick}}
<langsyntaxhighlight lang="ruby">require 'rubygems'
require 'RMagick'
 
Line 4,024 ⟶ 4,621:
 
draw.draw img
img.write "brownian_tree.bmp"</langsyntaxhighlight>
 
=={{header|Run BASIC}}==
[[File:BrownianTreeKokenge.png|thumb|right|]]
<langsyntaxhighlight lang="runbasic">numParticles = 3000
dim canvas(201,201)
graphic #g, 200,200
Line 4,048 ⟶ 4,644:
next i
render #g
#g "flush"</langsyntaxhighlight>
 
=={{header|Rust}}==
{{trans|D}}
{{libheader|rand}}
{{libheader|image}}
<langsyntaxhighlight lang="rust">
extern crate image;
extern crate rand;
 
use image::ColorType;
 
use rand::distributions::{IndependentSample, Range};
use std::cmp::{min, max};
use std::env;
use std::path::Path;
use std::process;
use rand::Rng;
 
fn help() {
Line 4,105 ⟶ 4,701:
width as u32,
height as u32,
ColorType::Gray(8)L8) {
Err(e) => println!("Error writing output image:\n{}", e),
Ok(_) => println!("Output written to:\n{}", output_path.to_str().unwrap()),
Line 4,116 ⟶ 4,712:
let mut field_base: Vec<_> = raw.as_mut_slice().chunks_mut(width).collect();
// Addressable 2d vector
let mut field: &mut [&mut [u8]] = field_base.as_mut_slice();
 
// Seed mote
field[width / 2][height / 2] = 1;
 
let walk_range = Range::new(-1i32, 2i32);
let x_spawn_range = Range::new(1usize, width - 1);
let y_spawn_range = Range::new(1usize, height - 1);
let mut rng = rand::thread_rng();
 
Line 4,131 ⟶ 4,724:
}
 
let mut x=rng.gen_range(1usize..width-1);
// Spawn mote
let mut x y= x_spawn_rangerng.ind_samplegen_range(&mut rng1usize..height-1);
let mut y = y_spawn_range.ind_sample(&mut rng);
 
// Increment field value when motes spawn on top of the structure
Line 4,143 ⟶ 4,735:
loop {
let contacts = field[x - 1][y - 1] + field[x][y - 1] + field[x + 1][y - 1] +
field[x - 1][y] + field[x + 1][y] +
field[x - 1][y + 1] + field[x][y + 1] +
field[x + 1][y + 1];
 
if contacts > 0 {
Line 4,151 ⟶ 4,743:
break;
} else {
let xw = walk_rangerng.ind_samplegen_range(&mut rng-1..2) + x as i32;
let yw = walk_rangerng.ind_samplegen_range(&mut rng-1..2) + y as i32;
if xw < 1 || xw >= (width as i32 - 1) || yw < 1 || yw >= (height as i32 - 1) {
break;
Line 4,161 ⟶ 4,753:
}
}
}</langsyntaxhighlight>
For a 512 x 512 field and 65k100k motes, run time is 25around 200 s on ~20112019 hardware (PhenomRyzen II5 X43600X).
<center>[[File:Rust-Brownian-512-20k.png]]</center>
 
=={{header|Scala}}==
===Java Swing Interoperability===
<langsyntaxhighlight Scalalang="scala">import java.awt.Graphics
import java.awt.image.BufferedImage
 
Line 4,216 ⟶ 4,807:
 
new Thread(new BrownianTree).start()
}</langsyntaxhighlight>
 
=={{header|Scheme}}==
{{works with|Guile}}
<langsyntaxhighlight lang="scheme">; Save bitmap to external file
(define (save-pbm bitmap filename)
(define f (open-output-file filename))
Line 4,327 ⟶ 4,917:
 
; Save to a portable bitmap file
(save-pbm bitmap "brownian-tree.pbm")</langsyntaxhighlight>
[[File:Scheme-guile-brownian-tree-large.png]]
 
=={{header|Seed7}}==
[[File:browniantree.png|300px|thumb|right|Simple brownian tree produced with Seed7 program]]
The program below generates a small brownian tree. You can watch how it grows.
 
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "draw.s7i";
include "keybd.s7i";
Line 4,370 ⟶ 4,959:
world[py][px] := 1;
rect(SCALE * pred(px), SCALE * pred(py), SCALE, SCALE, white);
DRAW_FLUSHflushGraphic;
bumped := TRUE;
else
Line 4,378 ⟶ 4,967:
until bumped;
end for;
end func;</syntaxhighlight>
const proc: main is func
begin
screen(SIZE * SCALE, SIZE * SCALE);
KEYBOARD := GRAPH_KEYBOARD;
genBrownianTree(SIZE, 20000);
readln(KEYBOARD);
end func;</lang>
 
Original source: [http://seed7.sourceforge.net/algorith/graphic.htm#brownian_tree]
Line 4,392 ⟶ 4,973:
=={{header|SequenceL}}==
'''SequenceL Code:'''<br>
<langsyntaxhighlight lang="sequencel">import <Utilities/Random.sl>;
import <Utilities/Sequence.sl>;
 
Line 4,438 ⟶ 5,019:
j within 1 ... worldSize;
in
(World: world, Rand: seedRandom(seed), Point: (X: worldSize / 2, Y: worldSize / 2));</langsyntaxhighlight>
 
'''C++ Driver Code:'''<br>
{{libheader|CImg}}
<langsyntaxhighlight lang="c">#include <time.h>
#include <cstdlib>
#include "CImg.h"
Line 4,485 ⟶ 5,066:
 
return 0;
}</langsyntaxhighlight>
 
{{out}}
[http://i.imgur.com/OrB9tLI.gifv Output Video]
 
=={{header|Sidef}}==
{{trans|Raku}}
<langsyntaxhighlight lang="ruby">const size = 100
const mid = size>>1
const particlenum = 1000
Line 4,569 ⟶ 5,149:
}
 
display()</langsyntaxhighlight>
{{out}}
<pre>
Line 4,610 ⟶ 5,190:
▀█
</pre>
=={{header|Simula}}==
<syntaxhighlight lang="simula">BEGIN
INTEGER NUM_PARTICLES;
INTEGER LINES, COLUMNS;
INTEGER SEED;
 
NUM_PARTICLES := 1000;
LINES := 46;
COLUMNS := 80;
SEED := ININT;
BEGIN
PROCEDURE DRAW_BROWNIAN_TREE(WORLD); INTEGER ARRAY WORLD;
BEGIN
INTEGER PX, PY; COMMENT PARTICLE VALUES ;
INTEGER DX, DY; COMMENT OFFSETS ;
INTEGER I;
 
COMMENT SET THE SEED ;
PX := RANDINT(0,LINES-1,SEED);
PY := RANDINT(0,COLUMNS-1,SEED);
WORLD(PX,PY) := 1;
FOR I := 0 STEP 1 UNTIL NUM_PARTICLES - 1 DO BEGIN
COMMENT SET PARTICLE'S INITIAL POSITION ;
PX := RANDINT(0,LINES-1,SEED);
PY := RANDINT(0,COLUMNS-1,SEED);
WHILE TRUE DO BEGIN
COMMENT RANDOMLY CHOOSE A DIRECTION ;
DX := RANDINT(-1,1,SEED);
DY := RANDINT(-1,1,SEED);
IF DX + PX < 0 OR DX + PX >= LINES
OR DY + PY < 0 OR DY + PY >= COLUMNS THEN
BEGIN
COMMENT PLOP THE PARTICLE INTO SOME OTHER RANDOM LOCATION ;
PX := RANDINT(0,LINES-1,SEED);
PY := RANDINT(0,COLUMNS-1,SEED);
END ELSE IF WORLD(PX + DX, PY + DY) <> 0 THEN BEGIN
COMMENT BUMPED INTO SOMETHING ;
WORLD(PX, PY) := 1;
GO TO BREAK;
END ELSE BEGIN
PY := PY + DY;
PX := PX + DX;
END IF;
END WHILE;
BREAK:
END FOR;
END DRAW_BROWNIAN_TREE;
 
INTEGER ARRAY WORLD(0:LINES-1,0:COLUMNS-1);
INTEGER I,J;
 
DRAW_BROWNIAN_TREE(WORLD);
 
FOR I := 0 STEP 1 UNTIL LINES-1 DO
BEGIN
FOR J := 0 STEP 1 UNTIL COLUMNS-1 DO
BEGIN
OUTCHAR(IF WORLD(I,J)=0 THEN '.' ELSE '*');
END;
OUTIMAGE;
END;
 
END;
END.</syntaxhighlight>
{{in}}
<pre>656565</pre>
{{out}}
<pre>
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
.........*.......***............*.*...**........................................
..........*......**..*.......*.****....*........................................
...........*******...**..*.*.*****....***.......................................
..........*.******....**.*.**.***....*.*........................................
.............****.****..**...***..*******............**.*.*.....................
..........*.*...**.*******...***...*****............***.****....................
...........*....*****.****..*..*****..***.*....*...*.*.****.....................
................*.****.*...****..*****.*****...*..******..*.....................
................*.********..**.*.*****.**.**..*.*.*****.***.....................
.........*...*...*.******..*.***.***...**********..**********...................
.........**.*......*******...********.*****.*****...**.*****.*.*................
..........**.*..*..***.*****.**.***.***.***.****.*.***.****.*.**................
..........*.*.****.**..**************.*..****.******.*..*******.................
...........*******.*.************.***********.****.*....*******.................
...........*.********..***.***.****.********.****.**....****.*..................
..........**..*****.**.***.*.***.*..*.**.**.********............................
...............*.*********..********..*.....**.****.*...........................
..............***.****.*****.*.***.*.**...*..*...***.*..........................
.........*...***.*.*..*****.***.********...**........*..........................
..........****...***.**.****************..**.**.*****...........................
.........***.***..****.*..******.******..***********............................
........***.**********....****.**.************.**.*.............................
........*.****.*..*******.***..**.**********.****..*............................
.......*........*.*.*...****..****.*******.*.***.*..............................
.......*.......*.......*****...**..****.****..***...............................
....................***.******..**..**.*****.....**.............................
.....................************.**..****.***..................................
...................*****.*.*.*.*****.**.******..................................
....................*.*.***...*****.**....**....................................
....................*.*****.....**.*..*..****...................................
......................*.***.....***......*****..................................
.........................*.*......****....**.**..*..............................
.................................*.......*..*.***.*.*...........................
..................................*.........******.*............................
..............................................**................................
................................................................................
................................................................................
................................................................................
................................................................................
</pre>
=={{header|Sinclair ZX81 BASIC}}==
Requires at least 2k of RAM. If you have more, you can plot it on a larger grid—up to and including full-screen, provided you don't mind spending literally hours watching the first few dots maunder about without hitting anything.
<langsyntaxhighlight lang="basic"> 10 DIM A$(20,20)
20 LET A$(10,10)="1"
30 FOR Y=42 TO 23 STEP -1
Line 4,636 ⟶ 5,334:
220 GOTO 130
230 LET A$(X,Y)="1"
240 NEXT I</langsyntaxhighlight>
{{out}}
Screenshot [http://www.edmundgriffiths.com/zx81browniantree.jpg here].
 
=={{header|Tcl}}==
{{libheader|Tk}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
package require Tk
 
Line 4,693 ⟶ 5,390:
update
makeBrownianTree 1000
brownianTree write tree.ppm</langsyntaxhighlight>
 
=={{header|TI-83 BASIC}}==
<langsyntaxhighlight lang="ti83b">:StoreGDB 0
:ClrDraw
:FnOff
Line 4,722 ⟶ 5,418:
:End
:Pause
:RecallGDB 0</langsyntaxhighlight>
 
=={{header|Uiua}}==
Uiua Pad will show well-shaped arrays as images directly. If running locally you can uncomment the final few lines to save it as a file instead. (Running local is ~10 times faster too.)
 
The main move loop passes round a pair of points: here and previous position, so when we hit a set cell we can just back up one.
 
<syntaxhighlight lang="Uiua">
S ← 80
# Create SxS grid, and set the centre point as seed.
⍜⊡(+1)↯2⌊÷2S ↯ S_S 0
 
RandInt ← ⌊×⚂
RandPoint ← ([⍥(RandInt S)2])
# Update the pair to be a new adjacent [[Here] [Last]]
Move ← ⊟∵(-1+⌊RandInt 3).⊢
In ← /××⊃(≥0)(<S) # Is this point in bounds?
# Given a grid return a free point pair and that grid.
SeedPair ← ⊟.⍢(RandPoint ◌)(=1⊡) RandPoint
# Find next adjacent position, or new seed if out of bounds.
Next ← ⟨SeedPair ◌|∘⟩:⟜(In ⊢)Move
# Start from a new Seed Pair and move until you hit the tree. Add the prior pos to the tree.
JoinTree ← ⍜⊡(+1)◌°⊟⍢Next (=0⊡⊢) SeedPair
# Do it multiple times.
⍜now⍥JoinTree500
 
# ◌
# &ime "png"
# &fwa "BrownianTree.png"
</syntaxhighlight>
 
Or if you like your code terse :-)
 
<syntaxhighlight lang="Uiua">
S ← 80
⍜⊡(+1)↯2⌊÷2S↯S_S0
Rp ← (⊟⍥(⌊×⚂S)2)
Sd ← ⊟.⍢(Rp◌)(=1⊡) Rp
Nx ← ⟨Sd◌|∘⟩:⟜(/××⊃(≥0)(<S)⊢)⊟∵(-1+⌊×⚂3).⊢
⍜now⍥(⍜⊡(+1)◌°⊟⍢Nx(=0⊡⊢)Sd)500
</syntaxhighlight>
{{out}}
[[File:UiuaBrownianTree.png|thumb|center||Sample with higher values than provided code]]
 
=={{header|Visual Basic .NET}}==
Windows Forms Application.
 
<langsyntaxhighlight lang="vbnet">
Imports System.Drawing.Imaging
 
Line 4,857 ⟶ 5,595:
End Sub
End Class
</syntaxhighlight>
</lang>
{{out|Final output}}
[[File:SH_BrownianTree.jpg]]
=={{header|Wren}}==
{{libheader|DOME}}
{{trans|Go}}
As you'd expect, not very fast so have halved Go's parameters to draw the tree in around 45 seconds.
<syntaxhighlight lang="wren">import "graphics" for Canvas, Color
import "dome" for Window
import "random" for Random
 
var Rand = Random.new()
 
var N8 = [
[-1, -1], [-1, 0], [-1, 1],
[ 0, -1], [ 0, 1],
[ 1, -1], [ 1, 0], [ 1, 1]
]
 
class BrownianTree {
construct new(width, height, particles) {
Window.title = "Brownian Tree"
Window.resize(width, height)
Canvas.resize(width, height)
_w = width
_h = height
_n = particles
}
 
init() {
Canvas.cls(Color.brown)
// off center seed position makes pleasingly asymetrical tree
Canvas.pset(_w/3, _h/3, Color.white)
var x = 0
var y = 0
var a = 0
while (a < _n) {
// generate random position for new particle
x = Rand.int(_w)
y = Rand.int(_h)
var outer = false
var p = Canvas.pget(x, y)
if (p == Color.white) {
// as position is already set, find a nearby free position.
while (p == Color.white) {
x = x + Rand.int(3) - 1
y = y + Rand.int(3) - 1
var ok = x >= 0 && x < _w && y >= 0 && y < _h
if (ok) {
p = Canvas.pget(x, y)
} else { // out of bounds, consider particle lost
outer = true
a = a + 1
break
}
}
} else {
// else particle is in free space
// let it wonder until it touches tree
while (!hasNeighbor(x, y)) {
x = x + Rand.int(3) - 1
y = y + Rand.int(3) - 1
var ok = x >= 0 && x < _w && y >= 0 && y < _h
if (ok) {
p = Canvas.pget(x, y)
} else { // out of bounds, consider particle lost
outer = true
a = a + 1
break
}
}
}
if (outer) continue
// x, y now specify a free position touching the tree
Canvas.pset(x, y, Color.white)
a = a + 1
// progress indicator
if (a % 100 == 0) System.print("%(a) of %(_n)")
a = a + 1
}
}
 
hasNeighbor(x, y) {
for (n in N8) {
var xn = x + n[0]
var yn = y + n[1]
var ok = xn >= 0 && xn < _w && yn >= 0 && yn < _h
if (ok && Canvas.pget(xn, yn) == Color.white) return true
}
return false
}
 
update() {}
 
draw(alpha) {}
}
 
var Game = BrownianTree.new(200, 150, 7500)</syntaxhighlight>
 
=={{header|XPL0}}==
[[File:BrownXPL0.gif|right]]
<langsyntaxhighlight XPL0lang="xpl0">include c:\cxpl\codes; \intrinsic 'code' declarations
def W=128, H=W; \width and height of field
int X, Y;
Line 4,880 ⟶ 5,713:
if KeyHit then [SetVid(3); quit]; \restore text mode
];
]</langsyntaxhighlight>
 
=={{header|zkl}}==
This grows rather slowly, so I've added a circle for barnacles to attach to. It looks like tendrils growing from the center to the circle and vice versa. The tree type is similar to that shown in the XPLO and Visual Basic .NET solutions.
Line 4,888 ⟶ 5,720:
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl
[[File:Brownian.zkl.jpg|250px|thumb|right]]
<langsyntaxhighlight lang="zkl">w:=h:=400; numParticles:=20_000;
bitmap:=PPM(w+2,h+2,0); // add borders as clip regions
 
Line 4,920 ⟶ 5,752:
}
}
bitmap.writeJPGFile("brownianTree.zkl.jpg"); // the final image</langsyntaxhighlight>
 
=={{header|ZX Spectrum Basic}}==
{{trans|Run BASIC}}
Very, very slow on a ZX Spectrum (even emulate and at maximum speed). Best use SpecBAS, changing the value of the variable np to 6000.
<langsyntaxhighlight lang="zxbasic">10 LET np=1000
20 PAPER 0: INK 4: CLS
30 PLOT 128,88
Line 4,941 ⟶ 5,772:
1020 LET y=RND*174
1030 RETURN
</syntaxhighlight>
</lang>
 
[[Category:Geometry]]
62

edits