Browse Source

new:CubeWithoutPerspective

master
kdxcxs 5 years ago
parent
commit
6e8a4e1d74
  1. BIN
      assets/CubeWithoutPerspective.gif
  2. 107
      src/python/CubeWithoutPerspective.py

BIN
assets/CubeWithoutPerspective.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

107
src/python/CubeWithoutPerspective.py

@ -0,0 +1,107 @@
# coding:utf-8
from tkinter import Tk, Canvas
import math, threading, time
class TkCube(object):
def __init__(self):
self.points = [[-1, 1, -1], # LeftFrontDown
[1, 1, -1], # RFD
[-1, -1, -1], # LBD
[1, -1, -1], # RBD
[-1, 1, 1], # LFU
[1, 1, 1], # RFU
[-1, -1, 1], # LBU
[1, -1, 1]] # RBU
self.pit = [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]] # point in 2d
self.angle = 0
self.speed = 1 # π/s
self.fps = 60
self.dist = [5, 4] # distance between the cube's center and focal point/canvas
self.st = 1 / self.fps # sleep time
self.apf = math.pi * self.speed / self.fps # angle per frame
# init canvas
self.tkroot = Tk()
self.cvs = [Canvas(self.tkroot, bg='white', width=800, height=600),
Canvas(self.tkroot, bg='white', width=800, height=600)]
self.cvs[0].pack()
self.showingCv = 0
self.hiddenCv = 1
self.runThread = threading.Thread(target=self.run)
def rotate(self):
self.angle += self.apf
if self.angle > 2 * math.pi:
self.angle -= 2 * math.pi
radius = math.sqrt(2) # 点旋转的半径
for pair in [[0, 4, -math.pi / 4],
[1, 5, math.pi / 4],
[2, 6, -math.pi * 3 / 4],
[3, 7, math.pi * 3 / 4]]: # rotate in pairs
center = [radius * math.cos(self.angle + pair[2]), radius * math.sin(self.angle + pair[2])]
# x
self.points[pair[0]][0] = center[0]
self.points[pair[1]][0] = center[0]
# y
self.points[pair[0]][1] = center[1]
self.points[pair[1]][1] = center[1]
def draw(self):
# 按照Y轴排序,筛去最远的点
self.points.sort(key=lambda t: t[1])
# 按Z轴排序,下层的点在前面,方便后面作画
self.points.sort(key=lambda t: t[2], reverse=True)
# project points into 2D canvas 投影到2D
for pt in range(8):
rate = self.dist[1] / (self.dist[0] + self.points[pt][1])
scale = 200
self.pit[pt][0] = self.points[pt][0] * rate * scale + 400 # 因为坐标原点在左上角,让x和y分别加400和300让画面在窗口中心
self.pit[pt][1] = self.points[pt][2] * rate * scale + 300
self.cvs[self.hiddenCv].delete('all')
for dcp, nps in [[1, [0, 3, 5]], # drawing central point:以1,2,4,7四个点为中心,分别连接相邻的三个点即可绘成正方体
[2, [0, 3, 6]],
[4, [0, 5, 6]],
[7, [3, 5, 6]]]:
for np in nps: # nearby point
self.cvs[self.hiddenCv].create_line(self.pit[dcp][0], self.pit[dcp][1],
self.pit[np][0],
self.pit[np][1])
# for pt in self.pit:
# self.cvs[self.hiddenCv].create_text(int(pt[0])+400,int(pt[1])+300,text=str(self.pit.index(pt)))
self.cvs[self.hiddenCv].create_polygon(self.pit[0][0], self.pit[0][1], self.pit[4][0], self.pit[4][1],
self.pit[5][0], self.pit[5][1], self.pit[1][0], self.pit[1][1],
fill='blue')
self.cvs[self.hiddenCv].create_polygon(self.pit[0][0], self.pit[0][1], self.pit[4][0], self.pit[4][1],
self.pit[6][0], self.pit[6][1], self.pit[2][0], self.pit[2][1],
fill='blue')
# self.cvs[self.hiddenCv].create_polygon(self.pit[0][0]-1, self.pit[0][1]-1, self.pit[4][0]-1, self.pit[4][1]+1,
# self.pit[5][0]+1, self.pit[5][1]+1, self.pit[1][0]+1, self.pit[1][1]-1,
# fill='blue')
# self.cvs[self.hiddenCv].create_polygon(self.pit[0][0]+1, self.pit[0][1]-1, self.pit[4][0]+1, self.pit[4][1]+1,
# self.pit[6][0]-1, self.pit[6][1]+1, self.pit[2][0]-1, self.pit[2][1]-1,
# fill='blue')
# 切换canvas
self.cvs[self.showingCv].pack_forget()
self.cvs[self.hiddenCv].pack()
self.showingCv, self.hiddenCv = self.hiddenCv, self.showingCv
def run(self):
while True:
# self.rotateThread = threading.Thread(target=self.rotate)
# self.rotateThread.run()
# self.drawThread = threading.Thread(target=self.draw)
# self.drawThread.run()
self.rotate()
self.draw()
# print(self.points)
time.sleep(self.st)
def start(self):
self.runThread.start()
self.tkroot.mainloop()
if __name__ == '__main__':
tc = TkCube()
tc.start()
Loading…
Cancel
Save