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.

def Load(aGrid, nX, nY, n):

    # 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'    

History