Task: Brownian tree




Go: package main

import (
    "fmt"
    "image"
    "image/color"
    "image/png"
    "math/rand"
    "os"
)

const w = 400     
const h = 300     
const n = 15000   
const frost = 255 

var g *image.Gray

func main() {
    g = image.NewGray(image.Rectangle{image.Point{0, 0}, image.Point{w, h}})
    
    g.SetGray(w/3, h/3, color.Gray{frost})
generate:
    for a := 0; a < n; {
        
        rp := image.Point{rand.Intn(w), rand.Intn(h)}
        if g.At(rp.X, rp.Y).(color.Gray).Y == frost {
            
            for {
                rp.X += rand.Intn(3) - 1
                rp.Y += rand.Intn(3) - 1
                
                if !rp.In(g.Rect) {
                    continue generate
                }
                if g.At(rp.X, rp.Y).(color.Gray).Y != frost {
                    break
                }
            }
        } else {
            
            
            for !hasNeighbor(rp) {
                rp.X += rand.Intn(3) - 1
                rp.Y += rand.Intn(3) - 1
                
                if !rp.In(g.Rect) {
                    continue generate
                }
            }
        }
        
        g.SetGray(rp.X, rp.Y, color.Gray{frost})
        a++
        
        if a%100 == 0 {
            fmt.Println(a, "of", n)
        }
    }
    f, err := os.Create("tree.png")
    if err != nil {
        fmt.Println(err)
        return
    }
    err = png.Encode(f, g)
    if err != nil {
        fmt.Println(err)
    }
    f.Close()
}

var n8 = []image.Point{
    {-1, -1}, {-1, 0}, {-1, 1},
    {0, -1}, {0, 1},
    {1, -1}, {1, 0}, {1, 1}}

func hasNeighbor(p image.Point) bool { 
    for _, n := range n8 {
        o := p.Add(n)
        if o.In(g.Rect) && g.At(o.X, o.Y).(color.Gray).Y == frost {
            return true
        }
    }
    return false
}





VB: Imports System.Drawing.Imaging

Public Class Form1

  ReadOnly iCanvasColor As Integer = Color.Black.ToArgb
  ReadOnly iSeedColor As Integer = Color.White.ToArgb

  Dim iCanvasWidth As Integer = 0
  Dim iCanvasHeight As Integer = 0

  Dim iPixels() As Integer = Nothing

  Private Sub BrownianTree()

    Dim oCanvas As Bitmap = Nothing
    Dim oRandom As New Random(Now.Millisecond)
    Dim oXY As Point = Nothing
    Dim iParticleCount As Integer = 0

    iCanvasWidth = ClientSize.Width
    iCanvasHeight = ClientSize.Height

    oCanvas = New Bitmap(iCanvasWidth, iCanvasHeight, Imaging.PixelFormat.Format24bppRgb)

    Graphics.FromImage(oCanvas).Clear(Color.FromArgb(iCanvasColor))

    iPixels = GetData(oCanvas)

    
    iParticleCount = CInt(iPixels.Length * 0.1)

    
    iPixels(oRandom.Next(iPixels.Length)) = iSeedColor

    
    For i As Integer = 0 To iParticleCount
      Do
        
        oXY = New Point(oRandom.Next(oCanvas.Width), oRandom.Next(oCanvas.Height))
      Loop While iPixels(oXY.Y * oCanvas.Width + oXY.X) = iSeedColor

      
      While Not CheckAdjacency(oXY)
        oXY.X += oRandom.Next(-1, 2)
        oXY.Y += oRandom.Next(-1, 2)

        
        If oXY.X < 0 Then oXY.X = 0 Else If oXY.X >= oCanvas.Width Then oXY.X = oCanvas.Width - 1
        If oXY.Y < 0 Then oXY.Y = 0 Else If oXY.Y >= oCanvas.Height Then oXY.Y = oCanvas.Height - 1
      End While

      iPixels(oXY.Y * oCanvas.Width + oXY.X) = iSeedColor

      
      
      
      
      
      
    Next

    oCanvas.Save("BrownianTree.bmp")
    BackgroundImage = oCanvas

  End Sub

  
  Private Function CheckAdjacency(ByVal XY As Point) As Boolean

    Dim n As Integer = 0

    For y As Integer = -1 To 1
      
      If (XY.Y + y < 0) OrElse (XY.Y + y >= iCanvasHeight) Then Continue For

      For x As Integer = -1 To 1
        
        If (XY.X + x < 0) OrElse (XY.X + x >= iCanvasWidth) Then Continue For

        
        If y <> 0 AndAlso x <> 0 Then
          n = (XY.Y + y) * iCanvasWidth + (XY.X + x)
          If iPixels(n) = iSeedColor Then Return True
        End If
      Next
    Next

    Return False

  End Function

  Private Function GetData(ByVal Map As Bitmap) As Integer()

    Dim oBMPData As BitmapData = Nothing
    Dim oData() As Integer = Nothing

    oBMPData = Map.LockBits(New Rectangle(0, 0, Map.Width, Map.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb)

    Array.Resize(oData, Map.Width * Map.Height)

    Runtime.InteropServices.Marshal.Copy(oBMPData.Scan0, oData, 0, oData.Length)

    Map.UnlockBits(oBMPData)

    Return oData

  End Function

  Private Sub SetData(ByVal Map As Bitmap, ByVal Data As Integer())

    Dim oBMPData As BitmapData = Nothing

    oBMPData = Map.LockBits(New Rectangle(0, 0, Map.Width, Map.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb)

    Runtime.InteropServices.Marshal.Copy(Data, 0, oBMPData.Scan0, Data.Length)

    Map.UnlockBits(oBMPData)

  End Sub

  Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    DoubleBuffered = True
    BackgroundImageLayout = ImageLayout.Center
    Show()
    Activate()
    Application.DoEvents()
    BrownianTree()
  End Sub
End Class