# 3D wrapper for turtle

I am a Python enthusiast, but I'm never sure if what I'm doing is Pythonic. I have made my own graphics wrapper for Python's turtle. I don't entirely know if I did this right, so I have come here for suggestions to make it run faster or improve the code in any way.

from turtle import *
from math import cos, sin, radians, atan

faceOn = False #These are metadata. Don't know what they're actually called.
active2D = []
active3D = []
activeLines = []
activeFaces = []
activeFacesTemp = []

def getpixels():
return active2D

def getverts():
return active3D

def getlines():
return activeLines

def getfaces():
return activeFaces

def begin(name, swidth, sheight):
title(name)
tracer(0,0)
screensize(swidth, sheight)
shapesize(1 / 20, 1 / 20)
shape('square')
ht()
penup()
update()

def Tcos(angle):

def Tsin(angle):

def rotate(vert, rot):
x,y,z = vert
Rx,Ry,Rz = rot
Ca,Cb,Cc = [Tcos(Rx), Tcos(Ry), Tcos(Rz)]
Sa,Sb,Sc = [Tsin(Rx), Tsin(Ry), Tsin(Rz)]

return [((x * Cb * Cc) + ((y * Sa * Sb * Cc) + (y * Ca * Sc)) + ((z * -Ca * Sb * Cc) + (z * Sa * Sc))),
((x * -Cb * Sc) + ((y * -Sa * Sb * Sc) + (y * Ca * Cc)) + ((z * Ca * Sb * Sc) + (z * Sa * Cc))),
((x * Sb) + (y * -Sa * Cb) + (z * Ca * Cb))]

def translate(vert, trans):
out = []
for x,y in zip(vert, trans):
out.append((x + y))
return out

def exits(string):
valid = {"OnClick":exitonclick, "Now":bye}
if string not in valid:
raise ValueError("Not a valid exit type")
else:
valid[string]()

def pix(point,upd):
goto(point[0], point[1])
stamp()
if upd == True:
update()
active2D.append([point, upd])

def vertex(point,fov,czd,upd):
x,y,z = vertdata(point)
pix([((-x * 2) / ((z / fov) - czd)), ((-y * 2) / ((z / fov) - czd))], upd)
active3D.append([point,[x,y,z],[fov,czd,upd]])

def vertdata(point):
return translate(rotate(point[0],point[1]),point[2])

def face_point(point,fov,czd):
x,y,z = vertdata(point)
if faceOn == True:
activeFacesTemp.append([point, [x, y, z], [fov, czd, upd]])
goto(((-x * 2) / ((z / fov) - czd)), ((-y * 2) / ((z / fov) - czd)))

def line(pointA,pointB,fov,czd,upd):
dataA,dataB = [vertdata(pointA), vertdata(pointB)]
Ax,Ay = [((-dataA[0] * 2) / ((dataA[2] / fov) - czd)), ((-dataA[1] * 2) / ((dataA[2] / fov) - czd))]
Bx,By = [((-dataB[0] * 2) / ((dataB[2] / fov) - czd)), ((-dataB[1] * 2) / ((dataB[2] / fov) - czd))]
if not (Bx - Ax) == 0:
else:
goto(Ax,Ay)
pendown()
goto(Bx,By)
penup()
activeLines.append([[pointA, pointB],
[[dataA[0], dataA[1], dataA[2]],
[dataB[0],dataB[1],dataB[2]]],[fov,czd,upd]])

def start_face(color):
fillcolor(color)
begin_fill()
faceOn = True

def end_face():
end_fill()
activeFaces.append(activeFacesTemp)
activeFacesTemp.clear()
faceOn = False

def flush(): #Used to empty the get...() methods, as well as clear the screen. Make sure to always use this instead of calling clear() from turtle.
active2D.clear()
activeLines.clear()
activeFaces.clear()
active3D.clear()
clear() #not listype.clear(), but a turtle method to clear the window.

def tick(x):
for q in range(x * 1000):
pass

def refresh():
update()

def example():
s = start_face
f = face_point
e = end_face
fov,czd = [500,5]
tra = [0,0,0]
x,y,z = [200,200,200]
for q in range(0,1440):
rot = [q,q,q]
vertA = [[x,y,z],rot,tra]
vertB = [[-x,y,z],rot,tra]
vertC = [[x,-y,z],rot,tra]
vertD = [[-x,-y,z],rot,tra]
vertE = [[x,y,-z],rot,tra]
vertF = [[-x,y,-z],rot,tra]
vertG = [[x,-y,-z],rot,tra]
vertH = [[-x,-y,-z],rot,tra]

flush()
f(vertE,fov,czd) #Faces first for translucency. Make sure all faces are the same color if Z buffer is not programmed.
s("Blue")
f(vertE,fov,czd)
f(vertF,fov,czd)
f(vertH,fov,czd)
f(vertG,fov,czd)
e()

f(vertA,fov,czd) #Second Face
s("Blue")
f(vertA,fov,czd)
f(vertB,fov,czd)
f(vertD,fov,czd)
f(vertC,fov,czd)
e()

f(vertC,fov,czd) #Third Face
s("Blue")
f(vertC,fov,czd)
f(vertD,fov,czd)
f(vertH,fov,czd)
f(vertG,fov,czd)
e()

f(vertA,fov,czd) #Forth Face
s("Blue")
f(vertA,fov,czd)
f(vertB,fov,czd)
f(vertF,fov,czd)
f(vertE,fov,czd)
e()

f(vertA,fov,czd) #Yay! All faces are done! We don't need a sixth face because it will always be covered by the other five.
s("Blue")
f(vertA,fov,czd)
f(vertC,fov,czd)
f(vertG,fov,czd)
f(vertE,fov,czd)
e()

line(vertC,vertD,fov,czd,False) #Line definitions. Make sure you do this first so you have an idea on the faces.
line(vertA,vertB,fov,czd,False)
line(vertB,vertD,fov,czd,False)
line(vertA,vertC,fov,czd,False)
line(vertD,vertH,fov,czd,False)
line(vertC,vertG,fov,czd,False)
line(vertE,vertG,fov,czd,False)
line(vertA,vertE,fov,czd,False)
line(vertH,vertF,fov,czd,False)
line(vertB,vertF,fov,czd,False)
line(vertH,vertG,fov,czd,False)
line(vertF,vertE,fov,czd,False)

refresh()
• Do you want style judgements too? Or just speed? – Riker Dec 1 '17 at 20:46
• @Riker Whatever you don't mind doing, I'm open too. I'm prioritizing speed but if you don't mind style judgments you can add those in too. – CoderBoy Dec 1 '17 at 20:48
• What's with the indenting in face_point? – Riker Dec 1 '17 at 21:06
• @Riker sorry I accidentally provided an error-laiden version before my latest revision. It should be good now – CoderBoy Dec 1 '17 at 21:18