Skip to content

Instantly share code, notes, and snippets.

Created October 20, 2009 20:59
Show Gist options
  • Save anonymous/214611 to your computer and use it in GitHub Desktop.
Save anonymous/214611 to your computer and use it in GitHub Desktop.
-- not ready !!!1!
import Random
data Point
-- X, Y
= Float Float
deriving (Show, Eq)
data Values = None
-- Point1, Angle1, Angle2, Point2
| Point Point Point Point
deriving (Show, Eq)
data Tree = Nil
| Trunk Values Tree Tree Tree
| Branch Values Tree Tree
deriving (Show, Eq)
data TreeType = NilType
| TrunkType
| BranchType
rollDice :: IO Int
rollDice = randomRIO (1,6)
rollType :: TreeType -> TreeType -> TreeType
rollType NilType expected = NilType
rollType BranchType expected
| r < 4 = BranchType
| r < 6 = expected
| otherwise = NilType
where r = rollDice
rollType TrunkType expected
| r < 3 = BranchType
| r < 6 = expected
| otherwise = TrunkType
where r = rollDice
--parent, start-size, end-size -> tree
grow :: TreeType -> Float -> Float -> Tree
grow NilType s e = Nil
grow TrunkType start end = Trunk None left middle right
where left = grow (rollType(TrunkType BranchType) start end)
middle = grow (rollType(TrunkType TrunkType) start end)
right = grow (rollType(TrunkType BranchType) start end)
grow BranchType start end = Branch None left right
where left = grow (rollType(BranchType NilType) start end)
right = grow (rollType(BranchType NilType) start end)
--start-size, end-size -> tree
makeTree :: Float -> Float -> Tree
makeTree start end
| start < 0 = Nil
| end < 0 = Nil
| start <= end = Nil
| otherwise = Trunk None Nil grow(TrunkType start end) Nil
from random import random, choice
from math import sin, cos, sqrt, pi, radians as rad
#data:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
class Tree:
color = "000000"
def __init__(self, value):
self.value = value
def __repr__(self):
return self.__class__.__name__+hex(id(self))[2:]
class Branch(Tree):
color = "2D5016"
def __init__(self, value, left=None, right=None):
super().__init__(value)
self.left = left
self.right = right
def __str__(self):
return "<{2} left:{0} right:{1}>".format(self.left,self.right,repr(self))
class Trunk(Branch):
color = "552200"
def __init__(self, value, left=None, middle=None, right=None):
super().__init__(value, left, right)
self.middle = middle
def __str__(self):
return "<{3} left:{0} middle:{1} right:{2}>".format(self.left,self.middle,self.right,repr(self))
class Value:
def __init__(self, parent, length, angle, size=None):
self.angle = angle
if parent:
pvalue = parent.value
if pvalue:
if size is None: size = pvalue.size - length/50
self.angle += pvalue.angle
self.point1 = pvalue.point2
self.point2 = Point(pvalue.point2.x+length*cos(rad(self.angle)),
pvalue.point2.y+length*sin(rad(self.angle)))
if size is None: size = 1
if size < 0: size = 0.2
self.size = size
#radom:
def rollType(previous, expected):
if type(previous) is not type: previous = type(previous)
types = [None, Branch, Branch, expected]
if previous == Branch: types += [Branch, None]
elif previous == Trunk: types += [Branch, Trunk, expected, Trunk]
return choice(types)
def rollLength(length):
return length - random()*10 - 1
def rollAngle(middle,range):
return middle - random() * choice([range, -range])
#code
def grow(parent, middle, length, stop):
if length < stop: return None
klass = rollType(parent, Trunk if isinstance(parent, Trunk) else Branch)
if not klass: return None
l = length*2 if klass == Trunk else length
result = klass(Value(parent, l,rollAngle(middle, 20)))
result.left = grow(result,-40, rollLength(length), stop)
if isinstance(result, Trunk):
result.middle = grow(result,0, rollLength(length), stop)
result.right = grow(result,40, rollLength(length), stop)
x = parent.value.point2.x - parent.value.point1.x
y = parent.value.point2.y - parent.value.point1.y
r = sqrt(x*x+y*y)+0.000000000001
v = length*0.9; x *= v/r; y *= v/r
x += result.value.point1.x
y += result.value.point1.y
result.value.angle1 = Point(x,y)
x, y = 0, 0
if isinstance(result, Branch):
if result.left:
x += result.left.value.point1.x - result.left.value.point2.x
y += result.left.value.point1.y - result.left.value.point2.y
if result.right:
x += result.right.value.point1.x - result.right.value.point2.x
y += result.right.value.point1.y - result.right.value.point2.y
if isinstance(result, Trunk):
if result.middle:
x += result.middle.value.point1.x - result.middle.value.point2.x
y += result.middle.value.point1.y - result.middle.value.point2.y
r = sqrt(x*x+y*y)+0.000000000001
v = length*0.8; x *= v/r; y *= v/r
x += result.value.point2.x
y += result.value.point2.y
result.value.angle2 = Point(x,y)
return result
def makeTree(x, y, size, start, stop):
result = Trunk(Value(None, start,-90,size))
result.value.point1 = result.value.angle1 = Point(x,y)
result.value.point2 = result.value.angle2 = Point(x,y-start)
result.middle = grow(result,0, start, stop)
return result
#output
def get_list(node):
result = []
if isinstance(node, Tree):
result += [(repr(node),node.value.point1.x,node.value.point1.y,
node.value.angle1.x,node.value.angle1.y,
node.value.angle2.x,node.value.angle2.y,
node.value.point2.x,node.value.point2.y,node.value.size,node.color)]
if isinstance(node, Branch):
result += get_list(node.left) + get_list(node.right)
if isinstance(node, Trunk):
result += get_list(node.middle)
return result
header = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.0"
width="210mm"
height="297mm"
id="svg2">
<defs id="defs4" />
"""
def print_it(tree):
l = get_list(tree)
svg = '<g id="{0}">'.format(repr(Tree(None)))
style = 'style="fill:none;fill-rule:evenodd;stroke:#{1};stroke-width:{0}px;'+\
'stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"'
for node in l:
s = style.format(*node[9:])
svg += '<path id="{1}" d="M {2:n},{3:n} C {4:n},{5:n} {6:n},{7:n} {8:n},{9:n}" {0} />'.format(s,*node)
svg += "</g>\n"
print(header+svg+"</svg>")
def main():
tree = makeTree(520,1000,30,90,50)
print_it( tree )
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment