Welcome, guest | Sign In | My Account | Store | Cart
```# PREAMBLE

# My original intention was to create some

# disruptive visual camoflage, inspired by the pattern on

# the bark of plane trees. The result was never quite what I intended

# and several fixes had to be incorperated to aproximate what I wanted.

# The end result is effective though and reminds me of a Jackson Pollock

# or a Monet painting.

# CODE

from Tkinter import *

from math import *

from random import*

# critical parameters, adjust to suit

W = 900     # canvas dimensions

H = 500

nLow    = 25   # recursive limiter

nLayers = 5    # number of repeated paint overs

nCover  = 0.8  # Adjusts probability of a particular area being painted over per sweep

nMSpan  = 5.0  # Same as above, These two parameters depend upon the number of recursions

nCSpan  = 2.0  # Same for colour range

# scale factor per recursion. i.e. not scale invariant

aScale  = [0.1, .3, .5, 0.5,0.9,0.9,0.1,0.1,0.1,0,0,0,0,0,0,0,0,0,0,0,0]

# colours are scale invariant

aColour = [0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5]

# The two functions AutumnPastels and DrawSplash

# can be modified to suit

def AutumnPastels(nCR, nCG, nCB):

# colour scheme

cR = ColStr(int((ZeroToOne(nCR, 8.0)) * 150) + 80) # red

cG = ColStr(int((ZeroToOne(nCG, 8.0)) * 150) + 80) # green

cB = ColStr(int((ZeroToOne(nCB, 8.0)) * 25) + 30)  # blue

return '#' + cR + cG + cB

def DrawSplash(nX, nY, colour):

# simulation of paint splatter or leaves

nX2 = dist(nX, nLow / 2.0)

nY2 = dist(nY, nLow / 2.0)

for i in range(8):

nX1 = dist(nX2, nLow / 3.0)

nY1 = dist(nY2, nLow / 3.0)

nL  = dist(nLow / 6.0 + 2, nLow / 3.0)

canvas.create_oval( nX1, nY1, nX1 + nL, nY1 + nL, fill = colour, width = 0)

canvas.update()

def ColStr( x):

if x > 255:

x = 0

if x < 0:

x = 255

s = "%x" % x # converts x into a hexidecimal string

if len( s) < 2:

s = '0' + s

return s

# This is a clumbsy way of recording continuity across the plane

# A dictionary would be more efficient, but it seems to work O.K.

# changes value if not set, or else it returns the value

if aGrid[nX][nY] == -1:

aGrid[nX][nY] = n

return n

return aGrid[nX][nY]

def ZeroToOne(nM, nSpan):

# maps the Real domain onto [0 , 1]

return atan(nM * nSpan) / pi + 0.5

def mid(n1, n2):

return int((n1 + n2) / 2)

def dist(nP, nScale):

return nP + (random() - 0.5) * nScale

def FracDown(aGrid, nX1, nY1, nX2, nY2, nTL, nTR, nBL, nBR, nLim, nRecursive, nCR, nCG, nCB):

# fractal lanscape grenerator

dx = nX2 - nX1

dy = nY2 - nY1

nS = aScale[nRecursive]

nT = dist((nTL + nTR) / 2, nS * nHorizFactor)

nL = dist((nTL + nBL) / 2, nS)

nR = dist((nTR + nBR) / 2, nS)

nB = dist((nBL + nBR) / 2, nS * nHorizFactor)

nM = dist((nTL + nTR + nBL + nBR) / 4, nS * nDiagFactor)

nSC = aColour[nRecursive]

nCR = dist(nCR, nSC)

nCG = dist(nCG, nSC)

nCB = dist(nCB, nSC)

nXm = mid(nX1, nX2)

nYm = mid(nY1, nY2)

if dx <= nLow and dy <= nLow:

if ZeroToOne(nM, nMSpan) > nLim:

DrawSplash(nXm, nYm, AutumnPastels(nCR, nCG, nCB))

return

nTL = Load(aGrid, nX1, nY2, nTL)

nTR = Load(aGrid, nX2, nY2, nTR)

nBL = Load(aGrid, nX1, nY1, nBL)

nBR = Load(aGrid, nX1, nY1, nBR)

t1  = (aGrid, nX1, nYm, nXm, nY2, nTL, nT,  nL,  nM,  nLim, nRecursive + 1, nCR, nCG, nCB)

t2  = (aGrid, nXm, nYm, nX2, nY2, nT,  nTR, nM,  nR,  nLim, nRecursive + 1, nCR, nCG, nCB)

t3  = (aGrid, nX1, nY1, nXm, nYm, nL,  nM,  nBL, nB,  nLim, nRecursive + 1, nCR, nCG, nCB)

t4  = (aGrid, nXm, nY1, nX2, nYm, nM,  nR,  nB,  nBR, nLim, nRecursive + 1, nCR, nCG, nCB)

aT  = [t1,t2,t3,t4]

shuffle(aT)

for i in aT:

apply(FracDown, i)

def Frac(nLim):

aGrid = []

for i in range(W):

aGrid.append([-1] * H)

FracDown(aGrid, 0, 0, W - 1, H - 1, 0.0, 0.0, 0.0, 0.0,nLim, 1, 0.0, 0.0, 0.0)

seed()

canvas = Canvas( width = W, height = H)

canvas.pack(side = TOP)

canvas.create_rectangle( 0, 0, W, H, fill = AutumnPastels(-0.8, -0.4, -3.0), width = 0, tag ='o')

nHorizFactor = (W + 0.0) / (H + 0.0)

nDiagFactor  = sqrt(H**2 + W**2) / (H + 0.0)

for i in range(nLayers):

Frac(nCover)

print 'done'
```