Animierte Rotation zweier Kugeln um eine feste Achse

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Joa
User
Beiträge: 14
Registriert: Samstag 21. Mai 2011, 12:49

Hallo,
ich programmiere noch nicht lange mit Python und bin dewegen noch etwas unerfahren.
Ich versuche gerade zwei Kugeln um eine feste Koordinaten-Achse animiert zu rotieren.

Mein Versuch sieht dabei so aus:

Code: Alles auswählen

from Tkinter import *
from vtk.tk.vtkTkRenderWidget import *
import vtk


def animation():
	global sphere1, sphere2
	
	t_matrix = ( 1 , 0 , 0 , 1.0,
			0 , 1 , 0 , 0,
			0 , 0 , 1 , 0,
			0 , 0 , 0 , 1)
			
	t1 = vtk.vtkTransform()
	t1.SetMatrix(t_matrix)
	
	rot = vtk.vtkTransform()
		
	for i in range (0,361):
		print i
		rot.RotateY(i)
		t1.Concatenate(rot)
		sphere1Act.SetUserMatrix(t1.GetMatrix())
		sphere2Act.SetUserMatrix(t1.GetMatrix())
		ren1.AddActor(sphere1Act)
		ren1.AddActor(sphere2Act)


root = Tk()

sphere1 = vtk.vtkSphereSource()
sphere1.SetCenter(3,3,3)
sphere1.SetRadius(0.25)

sphere1Map = vtk.vtkPolyDataMapper()
sphere1Map.SetInputConnection(sphere1.GetOutputPort())

sphere1Act = vtk.vtkActor()
sphere1Act.SetMapper(sphere1Map)

ren1=vtk.vtkRenderer()
ren1.AddActor(sphere1Act)
ren1.SetBackground(0.1, 0.2, 0.4)

s_prop1 = sphere1Act.GetProperty()
s_prop1.SetColor(0.0,1.0,1.0)

sphere2 = vtk.vtkSphereSource()
sphere2.SetCenter(-3,-3,-3)
sphere2.SetRadius(0.25)

sphere2Map = vtk.vtkPolyDataMapper()
sphere2Map.SetInputConnection(sphere2.GetOutputPort())

sphere2Act = vtk.vtkActor()
sphere2Act.SetMapper(sphere2Map)

ren1.AddActor(sphere2Act)

s_prop2 = sphere2Act.GetProperty()
s_prop2.SetColor(1.0,0.0,1.0)

rWidget = vtkTkRenderWidget(root, width='800', height='600')
rWidget.pack(expand='true', fill='both')
renWin = rWidget.GetRenderWindow()

renWin.AddRenderer(ren1)
renWin.SetSize(800,600)

iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

buttonQ = Button(root, text='quit', command=root.quit)
buttonQ.pack(expand='true', fill='x')

buttonS = Button(root, text='start/stop', command=animation)
buttonS.pack(expand='true', fill='x')

root.mainloop()

iren.Initialize()
iren.Start
Dabei soll bei Klick auf den Start/Stop Button die Funktion "animation" gestartet werden und die Kugeln einemal (360°) um die Y Achse rotieren. Jedoch funktioniert die Animation nicht.
Also bin ich irgendwie auf dem Holzweg, kann mir jemand einen Tipp geben wie ich die Animation zum laufen bekommen?

LG
Joa
Zuletzt geändert von Joa am Mittwoch 1. Juni 2011, 09:53, insgesamt 1-mal geändert.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

"Funktioniert nicht" ist keine besonders aussagekräftige Beschreibung. Was funktioniert wann nicht, woran erkennst du das es nicht funktioniert und was erwartest du, was passieren sollte? Wenn du deine Code noch so anpasst, dass er in Python-Codetags steht (einfach ein `=python` hinter `code`), dann hat dieser sogar richtiges Highlighting.

Sebastian
Das Leben ist wie ein Tennisball.
Joa
User
Beiträge: 14
Registriert: Samstag 21. Mai 2011, 12:49

Hey,
also die Kugeln bewegen sich nicht. Ich möchte das die Kugeln sich langsam um die Y Achse drehen und das im Anzeigen-Fenster zu sehen ist. Im Endeffekt soll man den Button Stat/Stop drücken, dann sollen die Kugeln sich zu drehen anfangen und wenn man wieder den Button Start/Stop drückt sollen sie aufhören sich zu drehen.
Oder benötige ich dafür einen Timer?

LG Joa
Yaso
User
Beiträge: 30
Registriert: Freitag 1. April 2011, 08:00

Spontan würde ich sagen, dass du dein Programm noch in Threads unterteilen musst, GUI/Berechnung, sonst blockierst du das GUI und es wird nicht aktualisiert.
Oder benötige ich dafür einen Timer?
Kann sein, je nach dem wie schnell die einzelnen Berechnungen durchgeführt werden.
Joa
User
Beiträge: 14
Registriert: Samstag 21. Mai 2011, 12:49

Wie unterteile ich das Programm am besten in Threads? Wie gesagt ich bin ein Python Neuling.
LG Joa
BlackJack

@Joa: Threads würde ich da eher nicht einsetzen, weil das im Zusammenhang mit GUIs immer etwas schwierig ist. VTK bietet doch auch Timer und Klassen für Animationen. Hast Du Dich damit schon mal auseinander gesetzt?

Noch zum Quelltext im ersten Beitrag: Der Aufruf von `root.mainloop()` kehrt erst zurück, wenn die Hauptschleife von `Tkinter` beendet wurde, also in der Regel erst wenn der Benutzer das Fenster geschlossen hat. Dann erst werden die Zeilen nach diesem Aufruf ausgeführt. Das ist wahrscheinlich eher nicht so gewollt. Und `iren.Start` möchtest Du dann vielleicht auch *aufrufen* — dazu fehlen aber Klammern.
Yaso
User
Beiträge: 30
Registriert: Freitag 1. April 2011, 08:00

BlackJack hat geschrieben:@Joa: Threads würde ich da eher nicht einsetzen, weil das im Zusammenhang mit GUIs immer etwas schwierig ist. VTK bietet doch auch Timer und Klassen für Animationen. Hast Du Dich damit schon mal auseinander gesetzt?
Kenne das VTK noch nicht, aber wenn das schon selber gute Klassen für Animationen hat, würde ich auch das einsetzen, denn Threads sind, wie von BlackJack erwähnt, wirklich etwas kompliziert im Zusammenhang mit GUIs.
Wie unterteile ich das Programm am besten in Threads? Wie gesagt ich bin ein Python Neuling.
Habe Threads nur mit GTK-GUI eingesetzt, darum kann ich dir leider nicht umbedingt weiterhelfen, da es dort eigene Thread-Klassen gibt.
Joa
User
Beiträge: 14
Registriert: Samstag 21. Mai 2011, 12:49

Mit einem Timer habe ich es versucht, aber es klappt irgendwie auch nicht, weil sich die GUI nicht updatet. Ich werde nochmal ein bischen lesen, vielleicht finde ich noch eine Idee.
Wenn sonst noch jemand eine Idee hat, immer her damit :-)
LG Joa
Joa
User
Beiträge: 14
Registriert: Samstag 21. Mai 2011, 12:49

So, ich habe jetzt ein bischen rumgebastelt und habe es hinbekommen, dass die Kugeln um ihren Ausgangspunkt rotieren. Das sieht dann wie folgt aus:

Code: Alles auswählen

from Tkinter import *
from vtk.tk.vtkTkRenderWidget import *
import vtk
import time

import math

class vtkTimerCallback():
   def __init__(self):
       self.timer_count = 0
 
   def execute(self,obj,event):	   
       print self.timer_count
       self.sphere1Act.SetPosition(-1+math.cos(self.timer_count/(2*math.pi)),1+math.sin(self.timer_count/(2*math.pi)),1);
       self.sphere2Act.SetPosition(-1+math.cos(self.timer_count/(2*math.pi)),1+math.sin(self.timer_count/(2*math.pi)),1);
       iren = obj
       iren.GetRenderWindow().Render()
       self.timer_count += 1
	   
def main():   
   sphere1 = vtk.vtkSphereSource()
   sphere1.SetCenter(3,3,3)
   sphere1.SetRadius(0.25)

   sphere1Map = vtk.vtkPolyDataMapper()
   sphere1Map.SetInputConnection(sphere1.GetOutputPort())

   sphere1Act = vtk.vtkActor()
   sphere1Act.SetMapper(sphere1Map)
   
   s_prop1 = sphere1Act.GetProperty()
   s_prop1.SetColor(0.0,1.0,1.0)   
   
   sphere2 = vtk.vtkSphereSource()
   sphere2.SetCenter(-3,-3,-3)
   sphere2.SetRadius(0.25)

   sphere2Map = vtk.vtkPolyDataMapper()
   sphere2Map.SetInputConnection(sphere2.GetOutputPort())

   sphere2Act = vtk.vtkActor()
   sphere2Act.SetMapper(sphere2Map)

   s_prop2 = sphere2Act.GetProperty()
   s_prop2.SetColor(1.0,0.0,1.0)

   ren1=vtk.vtkRenderer()
   renderWindow = vtk.vtkRenderWindow()
   
   renderWindow.AddRenderer(ren1);
   renderWindowInteractor = vtk.vtkRenderWindowInteractor()
   renderWindowInteractor.SetRenderWindow(renderWindow)

   ren1.AddActor(sphere1Act)
   ren1.AddActor(sphere2Act)
   ren1.SetBackground(0.1, 0.2, 0.4)

   renderWindow.Render()
 
   renderWindowInteractor.Initialize()

   cb = vtkTimerCallback()
   cb.sphere1Act = sphere1Act
   cb.sphere2Act = sphere2Act
   renderWindowInteractor.AddObserver('TimerEvent', cb.execute)
   timerId = renderWindowInteractor.CreateRepeatingTimer(100);

   renderWindowInteractor.Start()
 
 
if __name__ == '__main__':
   main()

Vielleicht hilft es ja mal jemand weiter
Antworten