Seite 1 von 1

Effiziente Darstellung vieler, vieler graphischer Elemente?

Verfasst: 5. Mai 2010 01:08
von ichbinsisyphos
Bild

Ich würde gern nur zum Spaß ein Programm schreiben, dass zweidimensional Stösse zwischen vielen Kugeln simuliert.

Seit ich von Python und PyQt auf C++ gewechselt habe, gehen die Berechnungen auch bei der einfachsten Implementation (jede Kugel wird gegen jede andere gecheckt) sehr fix.

NUR ... X maxed bei der Darstellung ab 40 Partikeln oder so eine Core völlig aus.


Im Moment verwende ich eine QGraphicsScene auf der ich die Partikel als QGraphicsEllipseItems verwalte.

Da das offensichtlich nicht zielführend ist, frage ich mich, was die effizienteste Art ist, die Darstellung zu machen ...


Ich habs noch nicht ausprobiert, aber jeden Durchgang eine neue QPixmap zu zeichnen und anzuzeigen kann auch nicht schlimmer sein.

Edit: Doch, QPixmap ist doch noch um einiges schlimmer.

Verfasst: 5. Mai 2010 07:47
von kater
Wie wäre es mit OpenGl? Damit kann man auch 2D Zeichnen. Gerade wenn es sich bewegt versagen die Qt Sachen alle.
Schau dir mal die Beispiele zu OpenGL an, ist nicht so schwer.

Btw. ist das die Braunsche Bewegung?

Verfasst: 5. Mai 2010 08:01
von Christian81
Bevor es komplett openGL wird kann man ja auch der View ein QGLWidget unterschieben und schauen obs was bringt...

Verfasst: 5. Mai 2010 14:22
von ichbinsisyphos
Ok, ich werd mir OpenGL mal zu Gemüte führen, ich hab mir gestern schon die Klassen durchgesehen, aber es scheint, als würde das alles anders funktionieren und ziemlich viel Zeit beanspruchen.


Ja, das ist quasi ein einfaches Modell der Braunschen Bewegung, also viele Kugeln die durch elastische Stöße Energien austauschen, wobei die Gesamtenergie - temperaturabhängig - konstant bleibt.

Verfasst: 5. Mai 2010 15:30
von kater
Wenn du es fertig hast, zeig mal. Das klingt interesannt.

Wenn du zwischen den "Atom" Kugeln noch größere schwerere Kugeln plazierst und die sich mit bewegen wäre das genial :)

Verfasst: 6. Mai 2010 06:41
von ichbinsisyphos
setViewport(new QGLWidget) für QGraphicsView funktioniert gut, aber Antialiasing funktioniert hier nicht mehr? Die üblichen Methoden haben überhaupt keinen Effekt und bei der GL-spezifischen Option "HighQualityAntialiasing" wird nur der weiße Untergrund angezeigt.





kater hat geschrieben:Wenn du es fertig hast, zeig mal. Das klingt interesannt.

Wenn du zwischen den "Atom" Kugeln noch größere schwerere Kugeln plazierst und die sich mit bewegen wäre das genial :)
Das meiste des Programms hab ich fast eins zu eins von einem alten Python-Programm von mir übernommen, dass ich geschrieben habe als ich grade zu programmieren angefangen habe. Und ich fürchte, ich komm bis zum Ende des Sommers nicht dazu es zu kommentieren und auch nur so weit zu ändern, dass es mir nicht mehr peinlich sein muss ;-)

Aber wenn du sowas selbst vor hast: Für die Kugeln gibts eine Klasse die Radius, x-, y-Position, x-,y-Geschwindigkeit und Masse enthält. Dann eine Methode, die einen Bewegungsschritt ausführt, also da wird einfach zur Position die Geschwindigkeit addiert.


Die Kollision wird das eigentlich interessante sein. Die Physik/Mathematik dahinter ist...
Kugeln stoßen, wenn ihr Mittelpunktsabstand <= die Summe ihrer Radien ist.
Sie stossen entlang der Verbindungslinie ihrer Mittelpunkte, die Geschwindigkeitskomponenten normal darauf bleiben erhalten. Bei Stößen mit der Wand wechselt die Normalgeschwindigkeit das Vorzeichen, Tangentialgeschwindigkeit bleibt gleich.

Günstigerweise betrachtet man den Stoß zwischen zwei Kugeln im Schwerpunktssystem, da wechseln die Geschwindigkeiten einfach das Vorzeichen und man muss die Massen nur bei der Berechnung der Schwerpunktsbewegung berücksichtigen.

Also werden einfach ein paar Transformationen gemacht:
* Teilchengeschwindigkeiten relativ zur gemeinsamen Schwerpunktsbewegung
* Davon die Komponenten entlang und normal auf die Verbindungsachse
* Geschwindigkeit normal drauf bleibt gleich, die andere wechselt das Vorzeichen, Schwerpunktsbewegung ist sowieso erhalten
* Rücktransformation ins ursprüngliche Koordinatensystem (x-,y-Achse) und ins ortsfeste System


Ich kann dir ein Schnippsel anbieten, da erkennt man auch ungefähr das Chaos
http://pastebin.com/QzLuxRW3

Das meiste ist nur mühsam und unübersichtlich, aber die Positionskorrektur ist ein ganz übler hack. Allgemein werden sich, wenn eine Kollision erkannt wird, die Grenzflächen einander nicht genau berühren, sondern sich überschneiden. Daraus ergeben sich ganz interessante Probleme, zum Teil bleiben die Kugeln aneinander kleben. Deswegen verschiebe ich vor dem Stoß beide Kugeln um den gleichen Betrag entlang der Verbindungslinie, soweit bis sie sich genau berühren. Das ergibt aber einen Fehler der besonders auffällt, wenn man wie du geschrieben hast ein schweres Teilchen reingibt: Impulsübertrag von leichten Teilchen hat kaum eine Auswirkung, aber durch die Positionskorrektur springt es wild herum.
Deswegen ist das eines der ersten Dinge, die ich, wenn ich mal Zeit habe, ändern muss.

Von n Kugeln jede gegen jede andere zu checken braucht n²/2 Berechnungen pro Schritt. Effektiv wäre die Verwendung eines quadtrees, aber das überfordert mich in C++ im Moment auch völlig.

Verfasst: 6. Mai 2010 07:29
von kater
Hehe, ja ich kenen das Problem der Kollisionen.

Und zwar geht es um ein Projekt von mir dieses Semesters. Wir nehmen mit dem Mikroskop winzig kleine Partikel auf die etwa so 200nm groß sind. Diese werden von der Wärmebewegung der Atome hin und her geschubst. Und aus dieser Bewegung kann man die Viskosität des Materials berechnen.
Viskosität ist irgendwie ein Wert ob etwas dick oder dünflüssig ist.