Code: Alles auswählen
#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
import Tkinter as tk
from collections import namedtuple
from math import cos, sin
from random import random
class Point(namedtuple('Point', 'x y z')):
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y, self.z + other.z)
def __mul__(self, number):
return Point(self.x * number, self.y * number, self.z * number)
def rotated(self, alpha=0, beta=0, gamma=0):
return Point(
(
self.x * cos(gamma) * cos(beta)
+ self.y * (
-sin(gamma) * cos(alpha)
+ cos(gamma) * sin(beta) * sin(alpha)
)
+ self.z * (
sin(gamma) * sin(alpha)
+ cos(gamma) * sin(beta) * cos(alpha)
)
),
(
self.x * sin(gamma) * cos(beta)
+ self.y * (
cos(gamma) * cos(alpha)
+ sin(gamma) * sin(beta) * sin(alpha)
)
+ self.z * (
-cos(gamma) * sin(alpha)
+ sin(gamma) * sin(beta) * cos(alpha)
)
),
(
self.x * -sin(beta)
+ self.y * cos(beta) * sin(alpha)
+ self.z * cos(beta) * cos(alpha)
)
)
def projected(self, distance):
quotient = 1 - self.z / distance
return Point(self.x / quotient, self.y / quotient, 0)
class Mesh(object):
def __init__(self, vertices, edges):
self.vertices = vertices
self.edges = edges
self.tag = 'mesh{0}'.format(id(self))
def __add__(self, point):
return Mesh([v + point for v in self.vertices], self.edges)
def __mul__(self, number):
return Mesh([v * number for v in self.vertices], self.edges)
def rotated(self, alpha, beta, gamma):
return Mesh(
[v.rotated(alpha, beta, gamma) for v in self.vertices], self.edges
)
def projected(self, distance):
return Mesh([v.projected(distance) for v in self.vertices], self.edges)
def draw(self, canvas):
for start_index, end_index in self.edges:
start_point = self.vertices[start_index]
end_point = self.vertices[end_index]
canvas.create_line(
start_point.x, start_point.y, end_point.x, end_point.y,
tag=self.tag
)
def delete(self, canvas):
canvas.delete(self.tag)
class MeshUI(tk.Frame):
def __init__(self, parent, mesh, size):
tk.Frame.__init__(self, parent)
self.mesh = mesh
self.displayed_mesh = None
self.size = size
self.zoom_factor = size / 4
self.distance = self.size * 2
self.offset = Point(self.size / 2, self.size / 2, 0)
self.alpha, self.beta, self.gamma = 0, 0, 0
self.alpha_delta = random() * 0.025
self.beta_delta = random() * 0.025
self.gamma_delta = random() * 0.025
self.canvas = tk.Canvas(self, width=self.size, height=self.size)
self.canvas.pack(side=tk.TOP)
self.step()
def update_display(self):
if self.displayed_mesh:
self.displayed_mesh.delete(self.canvas)
self.displayed_mesh = (
(
self.mesh.rotated(self.alpha, self.beta, self.gamma)
* self.zoom_factor
).projected(self.distance) + self.offset
)
self.displayed_mesh.draw(self.canvas)
def step(self):
self.alpha += self.alpha_delta
self.beta += self.beta_delta
self.gamma += self.gamma_delta
self.update_display()
self.after(50, self.step)
def main():
cube = Mesh(
[
Point(1, 1, 1),
Point(-1, 1, 1),
Point(1, -1, 1),
Point(1, 1, -1),
Point(1, -1, -1),
Point(-1, -1, 1),
Point(-1, 1, -1),
Point(-1, -1, -1),
],
[
(0, 1),
(0, 2),
(0, 3),
(1, 5),
(1, 6),
(2, 4),
(2, 5),
(3, 4),
(3, 6),
(4, 7),
(5, 7),
(6, 7),
]
)
root = tk.Tk()
root.title('Rotating Cube')
mesh_ui = MeshUI(root, cube, 500)
mesh_ui.pack()
root.mainloop()
if __name__ == '__main__':
main()