Построение перспективной проекции трехмерного объекта. Фигура неправильно располагается
Можете помочь, фигура почему-то в углу появляется, в чем может быть проблема?
from tkinter import *
import math
def view_tr():
d = 600
ro = 300
global teta
global phi
for i in range(len(vx)):
vx[i] = round((wx[i] * (-1) * math.sin(teta)) + wy[i] * (math.cos(teta)))
vy[i] = round((wx[i] * (-1) * math.cos(phi) * math.cos(teta)) - wy[i] * math.cos(phi) * math.sin(teta) + wz[i] * (math.sin(phi)))
vz[i] = round((wx[i] * (-1) * math.sin(phi) * math.cos(teta)) - wy[i] * math.sin(phi) * math.sin(teta) - wz[i] * (math.cos(phi)) + ro)
sx[i] = round(d * (vx[i] / vz[i])) + (ww / 2)
sy[i] = round(d * (vy[i] / vz[i])) + (hh / 2)
def draw():
c.create_line(vx[0], vy[0], vx[1], vy[1])
c.create_line(vx[1], vy[1], vx[2], vy[2])
c.create_line(vx[2], vy[2], vx[3], vy[3])
c.create_line(vx[3], vy[3], vx[0], vy[0])
c.create_line(vx[0], vy[0], vx[4], vy[4])
c.create_line(vx[4], vy[4], vx[5], vy[5])
c.create_line(vx[5], vy[5], vx[6], vy[6])
c.create_line(vx[6], vy[6], vx[7], vy[7])
c.create_line(vx[7], vy[7], vx[4], vy[4])
c.create_line(vx[1], vy[1], vx[5], vy[5])
c.create_line(vx[2], vy[2], vx[6], vy[6])
c.create_line(vx[3], vy[3], vx[7], vy[7])
root = Tk()
ww = 600
hh = 400
c = Canvas(root, width=ww, height=hh, bg='#0099ff')
c.pack()
teta = math.pi/4
phi = math.pi/4
vx = [0, 0, 0, 0, 0, 0, 0, 0]
vy = [0, 0, 0, 0, 0, 0, 0, 0]
vz = [0, 0, 0, 0, 0, 0, 0, 0]
wx=[-50,50,50,-50,-50,50,50,-50]
wy=[-50,-50,50,50,-50,-50,50,50]
wz=[-50,-50,-50,-50,50,50,50,50]
sx = [0, 0, 0, 0, 0, 0, 0, 0]
sy = [0, 0, 0, 0, 0, 0, 0, 0]
view_tr()
def up():
global teta
global phi
phi += 0.1
c.create_rectangle(0,0,ww,hh,fill='#0099ff')
view_tr()
draw()
def down() :
global teta
global phi
phi -= 0.1
c.create_rectangle(0,0,ww,hh,fill='#0099ff')
view_tr()
draw()
def left():
global teta
global phi
teta -= 0.1
c.create_rectangle(0,0,ww,hh,fill='#0099ff')
view_tr()
draw()
def right():
global teta
global phi
teta += 0.1
c.create_rectangle(0,0,ww,hh,fill='#0099ff')
view_tr()
draw()
b2 = Button(text='Лево', command = left, padx="70")
b2.pack(side=LEFT, fill=Y)
b4 = Button(text='Право', command = right, padx="70")
b4.pack(side=RIGHT, fill=Y)
b1 = Button(text='Вверх', command = up, pady="15")
b1.pack(side=TOP, fill=X)
b3 = Button(text='Вниз', command = down, pady="15")
b3.pack(side=BOTTOM, fill=X)
root.mainloop()
Ответы (1 шт):
Автор решения: insolor
→ Ссылка
В функции draw вы рисуете по объемным координатам (vx, vy), которые отсчитываются от нуля, а для canvas координата 0, 0 - это левый верхний угол. Нужно рисовать по экранным координатам (sx, sy), в них у вас начало координат смещается на середину экрана (к координатам по x и по y прибавляется половина ширины и высоты экрана соответственно):
sx[i] = round(d * (vx[i] / vz[i])) + (ww / 2)
sy[i] = round(d * (vy[i] / vz[i])) + (hh / 2)
Нужно в функции draw заменить все vx на sx и vy на sy:
def draw():
c.create_line(sx[0], sy[0], sx[1], sy[1])
c.create_line(sx[1], sy[1], sx[2], sy[2])
c.create_line(sx[2], sy[2], sx[3], sy[3])
c.create_line(sx[3], sy[3], sx[0], sy[0])
c.create_line(sx[0], sy[0], sx[4], sy[4])
c.create_line(sx[4], sy[4], sx[5], sy[5])
c.create_line(sx[5], sy[5], sx[6], sy[6])
c.create_line(sx[6], sy[6], sx[7], sy[7])
c.create_line(sx[7], sy[7], sx[4], sy[4])
c.create_line(sx[1], sy[1], sx[5], sy[5])
c.create_line(sx[2], sy[2], sx[6], sy[6])
c.create_line(sx[3], sy[3], sx[7], sy[7])
Результат:
Если нужна аксонометрическая (параллельная) проекция вместо перспективной, поменяйте вычисление экранных координат таким образом:
sx[i] = round(vx[i]) + (ww / 2)
sy[i] = round(vy[i]) + (hh / 2)
Результат:

