Как отобразить полигоны tkinter на холсте в трехмерных условиях? - PullRequest
0 голосов
/ 04 января 2019

Я пытаюсь создать программу, которая визуализирует объект в 3D и которую вы можете вращать и контролировать с помощью положения мыши. Я пытаюсь отобразить лица объекта, но не знаю, как мне сначала отобразить более близкие лица, чтобы перед более близкими лицами не отображалось «фоновое» лицо.

код, который я предоставил, полностью воспроизводим, просто скопируйте и вставьте его, если у вас есть tkinter и numpy.

from numpy import *
from tkinter import *

#eulers angles matrixes
def Rx(theta):
    return mat(mat([[1,     0     ,     0      ],
                    [0, cos(theta), -sin(theta)],
                    [0, sin(theta), cos(theta) ]]).round(15))

def Ry(theta):
    return mat(mat([[cos(theta), 0, -sin(theta)],
                    [    0     , 1,     0      ],
                    [sin(theta), 0, cos(theta) ]]).round(15))

def Rz(theta):
    return mat(mat([[cos(theta), -sin(theta), 0],
                    [sin(theta), cos(theta) , 0],
                    [    0     ,     0      , 1]]).round(15))
#returns a 2d projection matrix, 
def proj2d(p):
    return mat(eye(2,3)*p)

#tuple into vector
def vector(tuple):
    return transpose(mat(list(tuple)))

#updates position of the  3D point in function of the x,y,z angles
def position(pts3d,anglex,angley,anglez):
    for i in range(len(pts3d)):
        pts3d[i] = (float((Rx(anglex) * vector(pts3d[i]))[0]),
                    float((Rx(anglex) * vector(pts3d[i]))[1]),
                    float((Rx(anglex) * vector(pts3d[i]))[2]))
        pts3d[i] = (float((Ry(angley) * vector(pts3d[i]))[0]),
                    float((Ry(angley) * vector(pts3d[i]))[1]),
                    float((Ry(angley) * vector(pts3d[i]))[2]))
        pts3d[i] = (float((Rz(anglez) * vector(pts3d[i]))[0]),
                    float((Rz(anglez) * vector(pts3d[i]))[1]),
                    float((Rz(anglez) * vector(pts3d[i]))[2]))

#makes a projection of the 3d points on the 2d screen
def projected(pts3d):
    pts2d = []
    for i in pts3d:
        pts2d.append((float((proj2d(30+0.75*i[2]) * vector(i))[0]),
                      float((proj2d(30+0.75*i[2]) * vector(i))[1])))
    return pts2d

#displays dots
def dots(canvas,points):
    for i in points:
        canvas.create_oval(H/2+5+i[0],H/2+5+i[1],H/2-5+i[0],H/2-5+i[1],fill = 'white')

#displays vertices
def connect(canvas,vertics,points):
    for i in vertics:
        canvas.create_line(H/2+points[int(i[0])][0],H/2+points[int(i[0])][1],H/2+points[int(i[1])][0],H/2+points[int(i[1])][1],width = 2,fill = 'white')

#what I should modify, I guess: it's the funtion that displays the faces of the object
def face(canvas,faces,points,colors):
    for i in range(len(faces)):
        coordsface = ()
        for j in faces[i]:
            coordsface += (H/2+points[int(j)][0],H/2+points[int(j)][1])
        canvas.create_polygon(coordsface,fill = colors[i])

#major functions, updates position each time interval(delay)
def updateposition(self,H,canvas,points,vertics,faces,clrfc,delai,domegax,domegay,domegaz):
    canvas.delete('all')
    y,x = self.winfo_pointerx() - self.winfo_rootx() - H/2, self.winfo_pointery() - self.winfo_rooty() - H/2
    if abs(x) >= H/2 or abs(y) >= H/2: x,y = 0,0
    domegax -= 0.00001*(x)
    domegay -= 0.00001*(y)
    position(points,domegax,domegay,domegaz)
    if affpts == 'y':
        dots(canvas,projected(points))
    if affart == 'y':
        connect(canvas,vertics,projected(points))
    if afffac == 'y':
        face(canvas,faces,projected(points),clrfc)
    self.after(delai,updateposition,self,H,canvas,points,vertics,faces,clrfc,delai,domegax,domegay,domegaz)

## cube

def pts3Dcube():
    #points
    a = ( L/2, L/2, L/2)
    b = ( L/2, L/2,-L/2)
    c = ( L/2,-L/2, L/2)
    d = ( L/2,-L/2,-L/2)
    e = (-L/2, L/2, L/2)
    f = (-L/2, L/2,-L/2)
    g = (-L/2,-L/2, L/2)
    h = (-L/2,-L/2,-L/2)
    pts3d = [a,b,c,d,e,f,g,h]
    #vertices
    aretes = []
    for i in [0,2,4,6]:
        aretes.append(str(i)+str(i+1))
    for i in [0,1,4,5]:
        aretes.append(str(i)+str(i+2))
    for i in [0,1,2,3]:
        aretes.append(str(i)+str(i+4))
    #faces
    faces = ['0132','4576','0154','2376','1375','0264']
    clrfc = ['green','red','yellow','blue','orange','white']
    return pts3d, aretes, faces, clrfc

## initial conditions
L = 5
H = 600
delai = 5

self = Tk()
canvas = Canvas(self,height = H,width = H,bg = 'gray13')
canvas.pack()

objet = pts3Dcube() #object choice

domegax = 0.0
domegay = 0.0
domegaz = 0.0

#initial rotation angles
iomegax = 0
iomegay = 0
iomegaz = 0

#displaying points, vertices, faces or not
affpts = 'y'
affart = 'y'
afffac = 'y'

position(objet[0],iomegax,iomegay,iomegaz) #initial rotation
updateposition(self,H,canvas,objet[0],objet[1],objet[2],objet[3],delai,domegax,domegay,domegaz) # dynamic rotation

если у кого-то из вас есть идея, пожалуйста, прокомментируйте ее или что-то в этом роде, я заблудился. Спасибо!

...