Task: Brownian tree



C#: using System;
using System.Drawing;

namespace BrownianTree
{
    class Program
    {
        static Bitmap BrownianTree(int size, int numparticles)
        {
            Bitmap bmp = new Bitmap(size, size);
            Rectangle bounds = new Rectangle { X = 0, Y = 0, Size = bmp.Size };
            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.Clear(Color.Black);
            }
            Random rnd = new Random();
            bmp.SetPixel(rnd.Next(size), rnd.Next(size), Color.White);
            Point pt = new Point(), newpt = new Point();
            for (int i = 0; i < numparticles; i++)
            {
                pt.X = rnd.Next(size);
                pt.Y = rnd.Next(size);
                do
                {
                    newpt.X = pt.X + rnd.Next(-1, 2);
                    newpt.Y = pt.Y + rnd.Next(-1, 2);
                    if (!bounds.Contains(newpt))
                    {
                        pt.X = rnd.Next(size);
                        pt.Y = rnd.Next(size);
                    }
                    else if (bmp.GetPixel(newpt.X, newpt.Y).R > 0)
                    {
                        bmp.SetPixel(pt.X, pt.Y, Color.White);
                        break;
                    }
                    else
                    {
                        pt = newpt;
                    }
                } while (true);
            }
            return bmp;
        }

        static void Main(string[] args)
        {
            BrownianTree(300, 3000).Save("browniantree.png");
        }
    }
}








Fortran: program BrownianTree
  use RCImageBasic
  use RCImageIO

  implicit none

  integer, parameter :: num_particles = 1000
  integer, parameter :: wsize         = 800

  integer, dimension(wsize, wsize) :: world
  type(rgbimage) :: gworld
  integer :: x, y

  
  call init_random_seed
  
  world = 0
  call draw_brownian_tree(world)

  call alloc_img(gworld, wsize, wsize)
  call fill_img(gworld, rgb(0,0,0))
  
  do y = 1, wsize
     do x = 1, wsize
        if ( world(x, y) /= 0 ) then
           call put_pixel(gworld, x, y, rgb(255, 255, 255))
        end if
     end do
  end do

  open(unit=10, file='browniantree.ppm', action='write')
  call output_ppm(10, gworld)
  close(10)

  call free_img(gworld)

contains

  
  subroutine init_random_seed
    integer :: i, n, clock
    integer, dimension(:), allocatable :: seed

    call random_seed(size = n)
    allocate(seed(n))
    call system_clock(count = clock)
    seed = clock + 37 * (/ ( i - 1, i = 1, n) /)
    call random_seed(put = seed)
    deallocate(seed)
  end subroutine init_random_seed


  function randbetween(a, b) result(res) 
    integer, intent(in) :: a, b
    integer :: res

    real :: r

    call random_number(r)

    res = a + int((b-a)*r + 0.5)

  end function randbetween

  function bounded(v, ll, ul) result(res)
    integer, intent(in) :: v, ll, ul
    logical res

    res = ( v >= ll ) .and. ( v <= ul )
  end function bounded


  subroutine draw_brownian_tree(w)
    integer, dimension(:,:), intent(inout) :: w

    integer :: px, py, dx, dy, i
    integer :: xsize, ysize

    xsize = size(w, 1)
    ysize = size(w, 2)

    w(randbetween(1, xsize), randbetween(1, ysize)) = 1
    
    do i = 1, num_particles
       px = randbetween(1, xsize)
       py = randbetween(1, ysize)
       
       do
          dx = randbetween(-1, 1)
          dy = randbetween(-1, 1)
          if ( .not. bounded(dx+px, 1, xsize) .or. .not. bounded(dy+py, 1, ysize) ) then
             px = randbetween(1, xsize)
             py = randbetween(1, ysize)
          else if ( w(px+dx, py+dy) /= 0 ) then
             w(px, py) = 1
             exit
          else
             py = py + dy
             px = px + dx
          end if
       end do
    end do
    
  end subroutine draw_brownian_tree

end program