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.

# I think that the program does quite a good job of producing an aesteticalty

# pleasing picture, through a purely mathematical process,

# though some considerable tweeking on the part of the programmer

# was needed to achieve this.

# In this version, I am able to show a wide variety of colour schemes.

# Artists code their colours according to three dimensions, (hue, chorma and saturation)

# This might be a more apropriate approach than (red, green, blue).

# CODE

from Tkinter import *

from math import *

from random import*

# critical parameters, adjust to suit

W = 800        # canvas dimensions

H = 500        # golden ratio

nLow    = 25   # recursive limiter

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

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

nCSpan  = 8.0  # Same for colour range

nSplatterSize = 0.25

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

aScale  = [0.05, .1, .6, 0.9,0.9,0.3,0.1,0.1,0.1,0,0,0,0,0,0,0,0,0,0,0,0]

# colours

aColour = [0.5,0.0,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 VibrantHousePaint and DrawDrip

# can be modified to suit

def VibrantHousePaint(oM, nR):

# colour scheme

rg  = oM.rg

rb  = oM.rb

gb  = oM.gb

cR = ColStr(int((ZeroToOne(oM.r + rg - rb - oM.rgb , nCSpan * nR)) * nMaxR) + nMinR) # red

cG = ColStr(int((ZeroToOne(oM.g - rg + gb - oM.rgb , nCSpan * nR)) * nMaxG) + nMinG) # green

cB = ColStr(int((ZeroToOne(oM.b + gb - rb - oM.rgb , nCSpan * nR)) * nMaxB) + nMinB) # blue

return '#' + cR + cG + cB

def DrawDrip(nX, nY, oM, nR, bScheme):

colour = apply(bScheme, (oM, nR))

nL = (nLow + 0.0) * nR / 3

nX1 = dist(nX, nL * nSplatterSize)

nY1 = dist(nY, nL * nSplatterSize)

nL2 = dist(nL , nL)

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

canvas.create_rectangle( nX1, nY1 , nX1 + nL2 / 2.0, nY1 + nL2 / 2.0, fill = colour, width = 0)

canvas.update()

class splat:

def __init__(self,z,r,g,b,rg,rb,gb,rgb):

self.z   = z

self.r   = r

self.g   = g

self.b   = b

self.rg  = rg

self.rb  = rb

self.gb  = gb

self.rgb = rgb

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

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

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

cKey = str( nX) + '_' + str( nY)

if aGrid.has_key(cKey):

return aGrid[cKey]

aGrid[cKey] = n

return n

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 odist(A, nS1, nS2):

z = 0

r = 0

g = 0

b = 0

h = 0

v = 0

rg = 0

rb = 0

gb = 0

rgb = 0

for i in A:

z += i.z

r += i.r

g += i.g

b += i.b

rg += i.rg

rb += i.rb

gb += i.gb

rgb += i.rgb

l = len(A)

z = dist(z / l, nS1)

r = dist(r / l, nS2)

g = dist(g / l, nS2)

b = dist(b / l, nS2)

rg = dist(rg / l, nS2)

rb = dist(rb / l, nS2)

gb = dist(gb / l, nS2)

rgb = dist(rgb / l, nS2)

return splat(z, r, g, b, rg, rb, gb, rgb)

def FracDown(aGrid, nX1, nY1, nX2, nY2, oTL, oTR, oBL, oBR, nLim, nRecursive, bScheme):

# fractal lanscape grenerator

dx  = nX2 - nX1

dy  = nY2 - nY1

nS  = aScale[nRecursive]

nSC = aColour[nRecursive]

oT  = odist([oTL, oTR], nS * nHorizFactor, nSC)

oL  = odist([oTL, oBL], nS, nSC)

oR  = odist([oTR, oBR], nS, nSC)

oB  = odist([oBL, oBR], nS * nHorizFactor, nSC)

oM  = odist([oTL, oTR, oBL, oBR], nS * nDiagFactor, nSC)

nXm = mid(nX1, nX2)

nYm = mid(nY1, nY2)

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

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

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

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

if dx <= nLow and dy <= nLow:

if ZeroToOne(oM.z, nMSpan * sqrt(nRecursive)) > nLim:

DrawDrip(nXm, nYm, oM, sqrt(nRecursive), bScheme)

return

t1  = (aGrid, nX1, nYm, nXm, nY2, oTL, oT,  oL,  oM,  nLim, nRecursive + 1, bScheme)

t2  = (aGrid, nXm, nYm, nX2, nY2, oT,  oTR, oM,  oR,  nLim, nRecursive + 1, bScheme)

t3  = (aGrid, nX1, nY1, nXm, nYm, oL,  oM,  oBL, oB,  nLim, nRecursive + 1, bScheme)

t4  = (aGrid, nXm, nY1, nX2, nYm, oM,  oR,  oB,  oBR, nLim, nRecursive + 1, bScheme)

aT  = [t1,t2,t3,t4]

shuffle(aT)

for i in aT:

apply(FracDown, i)

def ColourRange():

nMin = int(random() * 255)

nMax = int(random() * 255)

if nMin > nMax:

nMin, nMax = nMax, nMin

return nMin, nMax - nMin

def Frac(nLim, bScheme):

aGrid = {}

s1 = splat(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0)

s2 = splat(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0)

s3 = splat(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0)

s4 = splat(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0)

FracDown(aGrid, 0, 0, W - 1, H - 1, s1, s2, s3, s4,nLim, 1, bScheme)

seed()

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

canvas.pack(side = TOP)

canvas.create_rectangle( 0, 0, W, H, fill = 'gray', width = 0)

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

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

nMinR, nMaxR = ColourRange()

nMinG, nMaxG = ColourRange()

nMinB, nMaxB = ColourRange()

Frac(nCover, VibrantHousePaint)

print 'done'
```