schlangenbeschwörer hat geschrieben:
Wie schreibe ich aber jetzt eine dynamische Funktion, die eine Animation erzeugt, bei der sich die Länge der Linie nicht verändert?
mfg, jj
Hi Schlangenbeschwörer,
das Zauberwort heißt "Mathematik"
. Ich sehe da zwei grundsetzliche Möglichkeiten:
a) Winkelfunktionen im rechtwinkligen Dreieck:
sin(w) * Laenge = GK
cos(w) * Laenge = AK
b) Satz des Pythagoras:
x**2 + y**2 = Laenge**2
Im ersten Fall zaehlst Du die Winkel hoch und berechnest den Abstand vom Mittelpunkt in x- und y-Richtung. Das führt zu einer gleichmäßigen Drehung, benötigt aber etwas Rechenleistung. Hier ein Beispiel:
Code: Alles auswählen
from Tkinter import *
class Rotor:
import Canvas, math, time, thread
def __init__(self, wMaster, center = (100, 100), length = 100, freq = 1, fps = 25):
self.fWinkelProTic = 2 * self.math.pi * freq / fps
self.iWaitTime = int(1000.0/fps)
self.fAktWinkel = 0.0
self.fRadius = float(length)/2
self.iX, self.iY = center
self.wMaster = wMaster
self.isRotating = False
self.Line = self.Canvas.Line(wMaster, 0, 0, 0, 0)
self.update_line()
def update_line(self):
fAbstandX = self.fRadius * self.math.sin(self.fAktWinkel)
fAbstandY = self.fRadius * self.math.cos(self.fAktWinkel)
self.Line.coords(((self.iX+fAbstandX, self.iY-fAbstandY), (self.iX-fAbstandX, self.iY+fAbstandY)))
def progress(self):
if self.isRotating:
self.fAktWinkel += self.fWinkelProTic
if self.fAktWinkel > self.math.pi: self.fAktWinkel -= self.math.pi
self.update_line()
self.wMaster.after(self.iWaitTime, self.progress)
def start(self):
if self.isRotating: return
self.isRotating = True
self.thread.start_new_thread(self.progress, ())
def stop(self):
self.isRotating = False
wCanvas = Canvas(width = 400, height = 200, bd = 3, relief = SUNKEN)
wCanvas.grid()
R1 = Rotor(wCanvas, center = (100, 100), length = 50, freq = 1, fps = 20)
R2 = Rotor(wCanvas, center = (200, 100), length = 70, freq = 0.5, fps = 15)
R3 = Rotor(wCanvas, center = (300, 100), length = 20, freq = -2)
R1.start()
R2.start()
R3.start()
wCanvas.mainloop()
Im zweiten Fall gibst Du einen Abstand vor und brauchst dann nur den anderen zu berechnen. Wenn Du den Vorgabeabstand aber linear veränderst, ergibt sich eine ungleichmäßige Rotation. Wenn Du dafür sorgst, dass Du immer den größeren Abstandswert veränderst (also sobald abs(a)>abs(b) ist, auf a als Vorgabewert umsteigen), sieht das eigentlich noch passabel aus.
Wenn es Dir auf Performance ankommt, kannst Du auch die Positionen der Linienpunkte für eine Umdrehung zwischenspeichern und brauchst sie dann nicht immer neu zu berechnen.
EDIT: Eigentlich reichen die Sinuswerte für 0.5 Radiant aus
Grüße,
der Michel