forked from mathuin/TopoMC
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tree.py
99 lines (88 loc) · 3.77 KB
/
tree.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# tree module
from __future__ import division
from random import random, randint
from mcarray import sealevel, setBlockAt, setBlockDataAt
# for minX, maxX, minZ, maxZ
import mcarray
from itertools import product
from multinumpy import SharedMemArray
from multiprocessing import Value
from numpy import zeros, int64, fromfunction, float32, sqrt
# tree constants
treeProb = 0.001
# If a tree canopy is about 20 units in area, then three trees
# in a 10x10 area would provide about 60% coverage.
forestProb = 0.03
# maximum distance from the trunk
treeWidth = 2
leafDistance = fromfunction(lambda i, j: sqrt((i-treeWidth)*(i-treeWidth)+(j-treeWidth)*(j-treeWidth)), (treeWidth*2+1, treeWidth*2+1), dtype=float32)
# [[ 4.24, 3.60, 3.16, 3.00, 3.16, 3.60, 4.24],
# [ 3.60, 2.82, 2.23, 2.00, 2.23, 2.82, 3.60],
# [ 3.16, 2.23, 1.41, 1.00, 1.41, 2.23, 3.16],
# [ 3.00, 2.00, 1.00, 0.00, 1.00, 2.00, 3.00],
# [ 3.16, 2.23, 1.41, 1.00, 1.41, 2.23, 3.16],
# [ 3.60, 2.82, 2.23, 2.00, 2.23, 2.82, 3.60],
# [ 4.24, 3.60, 3.16, 3.00, 3.16, 3.60, 4.24]]
# leaf pattern functions
def regularPattern(x, z, y, maxy):
return (leafDistance[x, z] <= (maxy-y+2)*treeWidth/maxy)
def redwoodPattern(x, z, y, maxy):
return (leafDistance[x, z] <= 0.75*((maxy-y+1)%(treeWidth+1)+1))
def birchPattern(x, z, y, maxy):
return (leafDistance[x, z] <= 1.2*(min(y, maxy-y+1)+1))
def shrubPattern(x, z, y, maxy):
return (leafDistance[x, z] <= 1.5*(maxy-y+1)/maxy+0.5)
def palmPattern(x, z, y, maxy):
return (y == maxy and leafDistance[x, z] < treeWidth+1)
# tree statistics
treeType = {
0 : 'Cactus',
1 : 'Regular',
2 : 'Redwood',
3 : 'Birch',
4 : 'Shrub'
}
treeCount = {}
for key in treeType.keys():
treeCount[key] = Value('i', 0)
# min height, max height, trunk height
treeHeight = [[3, 3, 3], [5, 7, 2], [9, 11, 2], [7, 9, 2], [1, 3, 0]]
leafPattern = [None, regularPattern, redwoodPattern, birchPattern, shrubPattern]
def printStatistics():
# NB: do not convert to logger
treeTuples = [(treeType[index], treeCount[index].value) for index in treeCount if treeCount[index].value > 0]
treeTotal = sum([treeTuple[1] for treeTuple in treeTuples])
print 'Tree statistics (%d total):' % treeTotal
for key, value in sorted(treeTuples, key=lambda tree: tree[1], reverse=True):
treePercent = (value*100)/treeTotal
print ' %d (%.2f%%): %s' % (value, treePercent, key)
def placeTree(x, z, elevval, probFactor, treeName):
if (x > mcarray.minX+treeWidth and z > mcarray.minZ+treeWidth and x < mcarray.maxX-treeWidth and z < mcarray.maxZ-treeWidth):
chance = random()
if (chance < probFactor):
treeNum = [key for key in treeType if treeType[key] == treeName][0]
makeTree(x, z, elevval, treeNum)
def makeTree(x, z, elevval, treeNum):
base = sealevel+elevval
height = randint(treeHeight[treeNum][0], treeHeight[treeNum][1])
leafbottom = base+treeHeight[treeNum][2]
maxleafheight = base+height+1
leafheight = maxleafheight-leafbottom
# special case cactus!
if (treeNum == 0):
[setBlockAt(x, base+y, z, 'Cactus') for y in xrange(height)]
else:
lxzrange = xrange(leafDistance.shape[0])
lyrange = xrange(leafheight)
for leafx, leafz, leafy in product(lxzrange, lxzrange, lyrange):
myleafx = x+leafx-treeWidth
myleafy = leafbottom+leafy
myleafz = z+leafz-treeWidth
if leafPattern[treeNum](leafx, leafz, leafy, leafheight-1):
setBlockAt(myleafx, myleafy, myleafz, 'Leaves')
setBlockDataAt(myleafx, myleafy, myleafz, treeNum-1)
for y in xrange(base,base+height):
setBlockAt(x, y, z, 'Wood')
setBlockDataAt(x, y, z, treeNum-1)
# increment tree count
treeCount[treeNum].value += 1