2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,4 +1,9 @@
Generate and draw a [[wp:Brownian tree|Brownian Tree]].
[[File:Brownian_tree.jpg|600px||right]]
;Task:
Generate and draw a   [[wp:Brownian tree|Brownian Tree]].
A Brownian Tree is generated as a result of an initial seed, followed by the interaction of two processes.
@ -6,4 +11,4 @@ A Brownian Tree is generated as a result of an initial seed, followed by the int
# Particles are injected into the field, and are individually given a (typically random) motion pattern.
# When a particle collides with the seed or tree, its position is fixed, and it's considered to be part of the tree.
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>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>

View file

@ -0,0 +1,11 @@
\\ 2 plotting helper functions 3/2/16 aev
\\ insm(): x,y are inside matrix mat (+/- p deep).
insm(mat,x,y,p=0)={my(xz=#mat[1,],yz=#mat[,1]);
return(x+p>0 && x+p<=xz && y+p>0 && y+p<=yz && x-p>0 && x-p<=xz && y-p>0 && y-p<=yz)}
\\ plotmat(): Simple plotting using matrix mat (filled with 0/1).
plotmat(mat)={
my(xz=#mat[1,],yz=#mat[,1],vx=List(),vy=vx,x,y);
for(i=1,yz, for(j=1,xz, if(mat[i,j]==0, next, listput(vx,i); listput(vy,j))));
plothraw(Vec(vx),Vec(vy));
print(" *** matrix(",xz,"x",yz,") ",#vy, " DOTS");
}

View file

@ -0,0 +1,20 @@
\\ 3/8/2016
BrownianTree1(size,lim)={
my(Myx=matrix(size,size),sz=size-1,sz2=sz\2,x,y,ox,oy);
x=sz2; y=sz2; Myx[y,x]=1; \\ seed in center
print(" *** START: ",x,"/",y);
for(i=1,lim,
x=random(sz)+1; y=random(sz)+1;
while(1,
ox=x; oy=y;
x+=random(3)-1; y+=random(3)-1;
if(insm(Myx,x,y)&&Myx[y,x],
if(insm(Myx,ox,oy), Myx[oy,ox]=1; break));
if(!insm(Myx,x,y), break);
);\\wend
);\\ fend i
plotmat(Myx);
}
{\\ Executing:
BrownianTree1(400,15000);
}

View file

@ -0,0 +1,18 @@
\\ 3/11/2016
BrownianTree2(size,lim)={
my(Myx=matrix(size,size),sz=size-1,dx,dy,x,y);
x=random(sz); y=random(sz); Myx[y,x]=1; \\ random seed
print(" *** START: ",x,"/",y);
for(i=1,lim,
x=random(sz)+1; y=random(sz)+1;
while(1,
dx=random(3)-1; dy=random(3)-1;
if(!insm(Myx,x+dx,y+dy), x=random(sz)+1; y=random(sz)+1,
if(Myx[y+dy,x+dx], Myx[y,x]=1; break, x+=dx; y+=dy));
);\\wend
);\\fend i
plotmat(Myx);
}
{\\ Executing:
BrownianTree2(1000,3000);
}

View file

@ -0,0 +1,20 @@
\\ 3/14/2016
BrownianTree3(size,lim)={
my(Myx=matrix(size,size),sz=size-2,x,y,dx,dy,b=0);
x=random(sz); y=random(sz); Myx[y,x]=1; \\ random seed
print("*** START: ", x,"/",y);
for(i=1,lim,
x=random(sz); y=random(sz);
b=0; \\ bumped not
while(!b,
dx=random(3)-1; dy=random(3)-1;
if(!insm(Myx,x+dx,y+dy), x=random(sz); y=random(sz),
if(Myx[y+dy,x+dx]==1, Myx[y,x]=1; b=1, x+=dx; y+=dy);
);
);\\wend
);\\fend i
plotmat(Myx);
}
{\\ Executing:
BrownianTree3(400,5000);
}

View file

@ -0,0 +1,27 @@
\\ 3/17/2016
\\ s=1/2(random seed/seed in the center); p=0..n (level of the "deep" checking).
BrownianTree4(size,lim,s=1,p=0)={
my(Myx=matrix(size,size),sz=size-3,x,y);
\\ seed s=1 for BTPB1, s=2 for BTPB2, BTPB3
if(s==1,x=random(sz); y=random(sz), x=sz\2; y=sz\2); Myx[y,x]=1;
print(" *** START: ",x,"/",y);
for(i=1,lim,
if(!(i==1&&s==2), x=random(sz)+1; y=random(sz)+1);
while(insm(Myx,x,y,1)&&
(Myx[y+1,x+1]+Myx[y+1,x]+Myx[y+1,x-1]+Myx[y,x+1]+
Myx[y-1,x-1]+Myx[y,x-1]+Myx[y-1,x]+Myx[y-1,x+1])==0,
x+=random(3)-1; y+=random(3)-1;
\\ p=0 for BTPB1, BTPB2; p=5 for BTPB3
if(!insm(Myx,x,y,p), x=random(sz)+1; y=random(sz)+1;);
);\\wend
Myx[y,x]=1;
);\\fend i
plotmat(Myx);
}
{
\\ Executing:
BrownianTree4(200,4000); \\BTPB1.png
BrownianTree4(200,4000,2); \\BTPB2.png
BrownianTree4(200,4000,2,5); \\BTPB3.png
}

View file

@ -0,0 +1,37 @@
boolean SIDESTICK = false;
boolean[][] isTaken;
void setup() {
size(512, 512);
isTaken = new boolean[width][height];
isTaken[width/2][height/2] = true;
}
void draw() {
for (int i = 0; i < width*height; i++) {
int x = floor(random(width));
int y = floor(random(height));
if (isTaken[x][y]) { continue; }
while (true) {
int xp = x + floor(random(-1, 2));
int yp = y + floor(random(-1, 2));
boolean iscontained = (
0 <= xp && xp < width &&
0 <= yp && yp < height
);
if (iscontained && !isTaken[xp][yp]) {
x = xp;
y = yp;
continue;
}
else {
if (SIDESTICK || (iscontained && isTaken[xp][yp])) {
isTaken[x][y] = true;
set(x, y, #000000);
}
break;
}
}
}
noLoop();
}

View file

@ -1,105 +1,105 @@
/*REXX program shows Brownian motion of dust in a field with one seed.*/
parse arg height width motes randSeed . /*get args from the C.L. */
if height=='' | height==',' then height=0 /*None? Use the default*/
if width=='' | width==',' then width=0 /* " " " " */
if motes=='' | motes==',' then motes='10%' /*% dust motes in field, */
/* ··· otherwise just the number.*/
tree = '*' /*an affixed dust speck (tree). */
mote = '·' /*char for a loose mote (of dust)*/
hole = ' ' /*char for an empty spot in field*/
clearScr = 'CLS' /*(DOS?) command to clear screen.*/
eons = 1000000 /* # cycles for Brownian movement*/
snapshot = 0 /*every n winks, show snapshot.*/
snaptime = 1 /*every n secs, show snapshot.*/
seedPos = 30 45 /*place seed in this field pos. */
seedPos = 0 /*if =0, use middle of the field.*/
/*if -1, use a random placement. */
/*otherwise, place it at seedPos.*/
/*set RANDSEED for repeatability.*/
if datatype(randSeed,'W') then call random ,,randSeed /*if #, use it*/
/* [↑] set the 1st random number*/
if height==0 | width==0 then _=scrsize() /*not all REXXes have SCRSIZE.*/
if height==0 then height=word(_,1)-3 /*adjust for border.*/
if width==0 then width=word(_,2)-1 /* " " " */
/*REXX program animates and displays Brownian motion of dust in a field (with one seed).*/
parse arg height width motes randSeed . /*get args from the C.L. */
if height=='' | height=="," then height=0 /*Not specified? Then use the default.*/
if width=='' | width=="," then width=0 /* " " " " " " */
if motes=='' | motes=="," then motes='10%' /*The % dust motes in the field, */
/* [↑] either a # -or- a # with a %.*/
tree = '*' /*an affixed dust speck, start of tree.*/
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*/
if datatype(randSeed,'W') then call random ,,randSeed /*if an integer, use the seed.*/
/* [↑] set the first random number. */
if height==0 | width==0 then _=scrsize() /*Note: not all REXXes have SCRSIZE BIF*/
if height==0 then height=word(_,1)-3 /*adjust useable height for the border.*/
if width==0 then width=word(_,2)-1 /* " " width " " " */
seedAt=seedPos
if seedPos== 0 then seedAt=width%2 height%2
if seedPos==-1 then seedAt=random(1,width) random(1,height)
parse var seedAt xs ys . /*obtain X & Y seed coördinates*/
/* [↓] if right-most≡'%', use %.*/
if right(motes,1)=='%' then motes=height * width * strip(motes,,'%') %100
@.=hole /*create the field, all empty. */
if seedPos== 0 then seedAt=width%2 height%2 /*if it's a zero, start in the middle.*/
if seedPos==-1 then seedAt=random(1,width) random(1,height) /*if negative, use random.*/
parse var seedAt xs ys . /*obtain the X and Y seed coördinates*/
/* [↓] if right-most ≡ '%', then use %*/
if right(motes,1)=='%' then motes=height * width * strip(motes,,'%') % 100
@.=hole /*create the Brownian field, all empty.*/
do j=1 for motes /*sprinkle # dust motes randomly.*/
do j=1 for motes /*sprinkle a # of dust motes randomly.*/
rx=random(1, width); ry=random(1,height); @.rx.ry=mote
end /*j*/ /* [↑] place a mote at random. */
/*plant the seed from which the */
/*tree will grow from dust motes */
@.xs.ys=tree /*that affixed themselves. */
call show /*show field before we mess it up*/
tim=0 /*the time (in secs) of last show*/
loX=1; hiX= width /*used to optimize mote searching*/
loY=1; hiY=height /* " " " " " */
end /*j*/ /* [↑] place a mote at random in field*/
/*plant the seed from which the tree */
/* will grow from dust motes that */
@.xs.ys=tree /* affixed themselves to others. */
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 winks=1 for eons until \motion /*EONs is used instead of ∞. */
motion=0 /*turn off Brownian motion flag. */
/*═══════════════════════════════════════ soooo, this is Brownian motion. */
do winks=1 for eons until \motion /*EONs is used instead of ∞, close 'nuf*/
motion=0 /*turn off the Brownian motion flag. */
if snapshot\==0 then if winks//snapshot==0 then call show
if snaptime\==0 then do; t=time('S')
if t\==tim & t//snaptime==0 then do
tim=time('s')
call show
end
if t\==tim & t//snaptime==0 then do; tim=time('s')
call show
end
end
minX=loX; maxX=hiX /*as the tree grows, the search */
minY=loY; maxY=hiY /* for dust motes gets faster. */
loX= width; hiX=1 /*used to limit mote searching. */
loY=height; hiY=1 /* " " " " " */
minX=loX; maxX=hiX /*as the tree grows, the search for */
minY=loY; maxY=hiY /* dust motes gets faster. */
loX= width; hiX=1 /*used to limit the mote searching. */
loY=height; hiY=1 /* " " " " " " */
do x =minX to maxX; xm=x-1; xp=x+1
do y=minY to maxY; if @.x.y\==mote then iterate
if x<loX then loX=x; if x>hiX then hiX=x /*is faster than: hiX=max(X hiX) */
if y<loY then loY=y; if y>hiY then hiY=y /*is faster than: hiY=max(y hiY) */
if @.xm.y ==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
if @.xp.y ==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
do x =minX to maxX; xm=x-1; xp=x+1 /*a couple handy-dandy values*/
do y=minY to maxY; if @.x.y\==mote then iterate /*Not a mote: keep looking. */
if x<loX then loX=x; if x>hiX then hiX=x /*faster than: hiX=max(X hiX)*/
if y<loY then loY=y; if y>hiY then hiY=y /*faster than: hiY=max(y hiY)*/
if @.xm.y ==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
if @.xp.y ==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
ym=y-1
if @.x.ym ==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
if @.xm.ym==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
if @.xp.ym==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
if @.x.ym ==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
if @.xm.ym==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
if @.xp.ym==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
yp=y+1
if @.x.yp ==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
if @.xm.yp==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
if @.xp.yp==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
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 mote actually move there ? */
@.x.y=hole /*empty out the old mote position*/
@.xb.yb=mote /*move the mote (or possibly not)*/
if xb<loX then loX=max(1,xb); if xb>hiX then hiX=min( width, xb)
if yb<loY then loY=max(1,yb); if yb>hiY then hiY=min(height, yb)
end /*y*/ /* [↑] limit the motes movement.*/
if @.x.yp ==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
if @.xm.yp==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
if @.xp.yp==tree then do; @.x.y=tree; iterate; end /*neighbor?*/
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 /*"empty out" the old mote position. */
@.xb.yb=mote /*move the mote (or possibly not). */
if xb<loX then loX=max(1, xb); if xb>hiX then hiX=min( width, xb)
if yb<loY then loY=max(1, yb); if yb>hiY then hiY=min(height, yb)
end /*y*/ /* [↑] limit mote's movement to field.*/
end /*x*/
call crop /*crops/truncates the mote field.*/
call crop /*crops (or truncates) the mote field.*/
end /*winks*/
call show
exit /*stick a fork in it, we're done.*/
/*────────────────────────────────CROP subroutine───────────────────────*/
crop: if loX>1 & hiX<width & loY>1 & hiY<height then return /*cropping?*/
do yc=-1 to height+1 by height+2 /*delete motes (moved off field).*/
do xc=-1 to width+1; if @.xc.yc==hole then iterate; @.xc.yc=hole
end /*xc*/
end /*yc*/
do xc=-1 to width+1 by width+2 /*delete motes (moved off field).*/
do yc=-1 to height+1; if @.xc.yc==hole then iterate; @.xc.yc=hole
end /*yc*/
end /*xc*/
return
/*────────────────────────────────SHOW subroutine───────────────────────*/
show: clearScr /*not necessary, but speeds it up*/
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*/

View file

@ -1,11 +1,12 @@
numParticles = 3000
dim canvas(201,201)
graphic #g, 200,200
#g fill("blue")
canvas(rnd(1) * 100 , rnd(1) * 200) = 1 'start point
for i = 1 To numParticles
x = (rnd(1) * 199) + 1
y = (rnd(1) * 199) + 1
while canvas(x+1, y+1) + canvas(x, y+1)+canvas(x+1, y)+canvas(x-1, y-1)+canvas(x-1, y)+canvas(x, y-1) = 0
while canvas(x+1, y+1)+canvas(x, y+1)+canvas(x+1, y)+canvas(x-1, y-1)+canvas(x-1, y)+canvas(x, y-1) = 0
x = x + (rnd(1)* 2) + 1
y = y + (rnd(1)* 2) + 1
If x < 1 Or x > 200 Or y < 1 Or y > 200 then
@ -14,13 +15,7 @@ for i = 1 To numParticles
end if
wend
canvas(x,y) = 1
#g "color green ; set "; x; " "; y
next i
graphic #g, 200,200
for x = 1 to 200
for y = 1 to 200
if canvas(x,y) = 1 then #g "color green ; set "; x; " "; y else #g "color blue ; set "; x; " "; y
next y
next x
render #g
#g "flush"

View file

@ -0,0 +1,107 @@
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;
fn help() {
println!("Usage: brownian_tree <output_path> <mote_count> <edge_length>");
}
fn main() {
let args: Vec<String> = env::args().collect();
let mut output_path = Path::new("out.png");
let mut mote_count: u32 = 10000;
let mut width: usize = 512;
let mut height: usize = 512;
match args.len() {
1 => {}
4 => {
output_path = Path::new(&args[1]);
mote_count = args[2].parse::<u32>().unwrap();
width = args[3].parse::<usize>().unwrap();
height = width;
}
_ => {
help();
process::exit(0);
}
}
assert!(width >= 2);
// Base 1d array
let mut field_raw = vec![0u8; width * height];
populate_tree(&mut field_raw, width, height, mote_count);
// Balance image for 8-bit grayscale
let our_max = field_raw.iter().fold(0u8, |champ, e| max(champ, *e));
let fudge = std::u8::MAX / our_max;
let balanced: Vec<u8> = field_raw.iter().map(|e| e * fudge).collect();
match image::save_buffer(output_path,
&balanced,
width as u32,
height as u32,
ColorType::Gray(8)) {
Err(e) => println!("Error writing output image:\n{}", e),
Ok(_) => println!("Output written to:\n{}", output_path.to_str().unwrap()),
}
}
fn populate_tree(raw: &mut Vec<u8>, width: usize, height: usize, mc: u32) {
// Vector of 'width' elements slices
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();
for i in 0..mc {
if i % 100 == 0 {
println!("{}", i)
}
// Spawn mote
let mut x = x_spawn_range.ind_sample(&mut rng);
let mut y = y_spawn_range.ind_sample(&mut rng);
// Increment field value when motes spawn on top of the structure
if field[x][y] > 0 {
field[x][y] = min(field[x][y] as u32 + 1, std::u8::MAX as u32) as u8;
continue;
}
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 {
field[x][y] = 1;
break;
} else {
let xw = walk_range.ind_sample(&mut rng) + x as i32;
let yw = walk_range.ind_sample(&mut rng) + y as i32;
if xw < 1 || xw >= (width as i32 - 1) || yw < 1 || yw >= (height as i32 - 1) {
break;
}
x = xw as usize;
y = yw as usize;
}
}
}
}

View file

@ -0,0 +1,16 @@
10 LET np=1000
20 PAPER 0: INK 4: CLS
30 PLOT 128,88
40 FOR i=1 TO np
50 GO SUB 1000
60 IF NOT ((POINT (x+1,y+1)+POINT (x,y+1)+POINT (x+1,y)+POINT (x-1,y-1)+POINT (x-1,y)+POINT (x,y-1))=0) THEN GO TO 100
70 LET x=x+RND*2-1: LET y=y+RND*2-1
80 IF x<1 OR x>254 OR y<1 OR y>174 THEN GO SUB 1000
90 GO TO 60
100 PLOT x,y
110 NEXT i
120 STOP
1000 REM Calculate new pos
1010 LET x=RND*254
1020 LET y=RND*174
1030 RETURN