75 lines
2.2 KiB
Python
Executable File
75 lines
2.2 KiB
Python
Executable File
#
|
|
# Code under the MIT license by Alexander Pruss
|
|
#
|
|
|
|
from mc import *
|
|
import drawing
|
|
from sys import argv
|
|
import mcpi.settings as settings
|
|
import ast
|
|
|
|
RAINBOW = (WOOL_RED,WOOL_PINK,WOOL_ORANGE,WOOL_YELLOW,WOOL_GREEN,WOOL_BLUE,WOOL_LIGHT_BLUE,WOOL_PURPLE)
|
|
|
|
TAN30 = sqrt(3.)/3
|
|
SQRT32 = sqrt(3./2)
|
|
|
|
def parseBlock(s):
|
|
try:
|
|
return ast.literal_eval(s)
|
|
except:
|
|
return globals()[s.upper()]
|
|
|
|
def distance(a,b):
|
|
return sqrt((a[0]-b[0])**2+(a[1]-b[1])**2+(a[2]-b[2])**2)
|
|
|
|
def tetrahedronBottom(height, apex):
|
|
side = SQRT32*height
|
|
return ( (apex[0]-0.5*TAN30*side,apex[1]-height,apex[2]-0.5*side),
|
|
(apex[0]-0.5*TAN30*side,apex[1]-height,apex[2]+0.5*side),
|
|
(apex[0]+TAN30*side,apex[1]-height,apex[2]) )
|
|
|
|
def drawTetrahedron(height, apex, block):
|
|
bottom = tetrahedronBottom(height, apex)
|
|
for i in range(int(round(height))+1):
|
|
triangle = []
|
|
for point in bottom:
|
|
a = float(i)/height
|
|
triangle.append(((1-a)*apex[0]+a*point[0],apex[1]-i,(1-a)*apex[2]+a*point[2]))
|
|
d.face(triangle,block)
|
|
return triangle
|
|
|
|
def average(a,b):
|
|
return tuple(0.5*(a[i]+b[i]) for i in range(len(a)))
|
|
|
|
def transform(tet):
|
|
level, height, apex = tet[0],tet[1],tet[2]
|
|
bottom = tetrahedronBottom(height,apex)
|
|
yield (level,height/2.,apex)
|
|
for p in bottom:
|
|
yield (level+1,height/2.,average(apex,p))
|
|
|
|
def sierpinski(height, x,y,z, level):
|
|
tetrahedra = [(0,height,(x,y,z))]
|
|
for i in range(level):
|
|
out = []
|
|
for tet in tetrahedra:
|
|
out += transform(tet)
|
|
tetrahedra = out
|
|
return tetrahedra
|
|
|
|
mc = Minecraft()
|
|
d = drawing.Drawing(mc)
|
|
pos = mc.player.getPos()
|
|
height = 240 if not settings.isPE else 128
|
|
levels = 7
|
|
mc.player.setPos(tetrahedronBottom(height,(pos.x,pos.y+height,pos.z))[0])
|
|
tetrahedra = sierpinski(height,pos.x,pos.y+height,pos.z,levels)
|
|
mc.postToChat("Drawing")
|
|
if len(argv) >= 2 and '__' not in argv[1]:
|
|
specifiedBlock = parseBlock(argv[1])
|
|
block = lambda level : specifiedBlock
|
|
else:
|
|
block = lambda level : RAINBOW[level % len(RAINBOW)]
|
|
for tet in tetrahedra:
|
|
drawTetrahedron(tet[1],tet[2],block(tet[0]))
|