Brownian tree

You are encouraged to solve this task according to the task description, using any language you may know.



Task

Generate and draw a   Brownian Tree.



A Brownian Tree is generated as a result of an initial seed, followed by the interaction of two processes.

 The initial "seed" is placed somewhere within the field. Where is not particularly important; it could be randomized, or it could be a fixed point.
 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. 



link graphics,printf
 
procedure main()             # brownian tree
 
Density  := .08              # % particles to area
SeedArea := .5               # central area to confine seed
ParticleArea := .7           # central area to exclude particles appearing
Height := Width := 400       # canvas
 
Particles := Height * Width * Density
Field := list(Height)
every !Field := list(Width)
 
Size := sprintf("size=%d,%d",Width,Height)
Fg   := sprintf("fg=%s",?["green","red","blue"])
Label := sprintf("label=Brownian Tree %dx%d PA=%d%% SA=%d%% D=%d%%",
         Width,Height,ParticleArea*100,SeedArea*100,Density*100)
WOpen(Label,Size,Fg,"bg=black") | stop("Unable to open Window")
 
sx := Height * SetInside(SeedArea)
sy := Width  * SetInside(SeedArea)
Field[sx,sy] := 1
DrawPoint(sx,sy)             # Seed the field
 
Lost := 0
 
every 1 to Particles do {
   repeat {
      px := Height * SetOutside(ParticleArea)
      py := Width  * SetOutside(ParticleArea)
      if /Field[px,py] then 
         break               # don't materialize in the tree
      }      
   repeat {
      dx := delta() 
      dy := delta()
      if not ( xy := Field[px+dx,py+dy] ) then {
         Lost +:= 1
         next                # lost try again
         }
      if \xy then
         break               # collision
 
      px +:= dx              # move to clear spot
      py +:= dy
      }
   Field[px,py] := 1
   DrawPoint(px,py)          # Stick the particle  
   }
printf("Brownian Tree Complete: Particles=%d Lost=%d.\n",Particles,Lost)
WDone()
end
 
procedure delta()            #: return a random 1 pixel perturbation
   return integer(?0 * 3) - 1
end
 
procedure SetInside(core)    #: set coord inside area 
   return core * ?0 + (1-core)/2
end
 
procedure SetOutside(core)   #: set coord outside area
   pt := ?0 * (1 - core)  
   pt +:= ( pt > (1-core)/2, core)
   return pt
end