Diskussion zum Thema Kollision und Reflexion - Elastischer Stoß

  • C#

Es gibt 50 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Diskussion zum Thema Kollision und Reflexion - Elastischer Stoß

    Jou Leute, da der Inhalts-Thread der Moderation unterliegt und ich ihn frei von Diskussionsbeiträgen halten möchte, eröffne ich hier einen Diskussionsthread dazu, wo wir Probleme benennen und diskutieren können.
    Wenn das zu einer substanziellen Weiterentwicklung des Stoß-Algorithmus führt, werde ich das dort dokumentieren und einpflegen.
    Den @ErfinderDesRades bitte ich, die Diskussion aus dem Thread Hilfe bei Erstellung einer Kollisionserkennung
    hier weiterzuführen. Vielleicht kann ein Moderator die betreffenden Beiträge hier anhängen.

    Beiträge (ab Hilfe bei Erstellung einer Kollisionserkennung) hier angehängt. ~Thunderbolt
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Thunderbolt“ ()

    naja, mittm wpf hätteste ja nix zu tun.
    Du hättest nur 2 Datenklassen - Ball, Schlaeger, mit ihren Properties Location, Speed (As Vector), Weight Weight könnte man sogar weglassen, wenn man annimmt, dass der Schläger unendliche Masse hat, also vom Ball nicht abgelenkt wird.
    Da wäre an dir einzig die Kollision zu berechnen, und bei Auftreten derselben den neuen Speed des Balls.

    Das ist doch Super-Einfach für dich, oder?
    @ErfinderDesRades OK.
    Wie komme ich denn hier zu einer Pong-mäßigen Anzeige?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    So - ich hab jetzt ein 3. Projekt in die Solution von Kein Pong - Erstaunliches mit ItemsControl.Itemspanel gemacht, wo ich die Objekte als Ball und Schläger designed hab.
    Und Kollision mit Wandung hab ich schon implementiert, und eine Architektur, die das Hinzufügen weiterer Kollisionstypen zum Kinderspiel macht.
    Ich hab sogar schon die Methode Ball.RacketCollision(racket) angelegt, allerdings leer.
    Diese Methode wäre quasi deine Baustelle, und sie hat Zugriff auf alle notwendigen Daten (nämlich Position, Abmasse und Geschw-Vektor der Objekte).
    Massen und Reibung habich nicht implementiert, ich nehme die Schläger-Masse als nahe unendlich an, also eine Kollision soll nur den Ball, nicht aber den Schläger ablenken.
    Gerne aber kannst du Massen einfügen, mw. auch Reibung oder verschiedene Abmasse, schräg gestellte oder verlaufende Schläger - was du wolle.

    Ich für mein Teil wäre schon erfreut, wenndes mit dem sehr vereinfachten Physik-Modell, wie es ist, hinbekommen tätest, dass der Schläger die Bälle schlägt.

    Ja, wie gesagt: Ich hab schoma Wandung-Kollision implementiert, prinzipiell auf gleiche Weise wäre die Schläger-Kollision auszuführen - wie gesagt: Sogar aufgerufen wird sie schon - nur - wie gesagt - tun tut sie noch nix. ;)
    @ErfinderDesRades Ich hab mal meinen ersten Entwurf eines Billiard-Spiels gepostet: Kollision und Reflexion - Elastischer Stoß
    Die Reflexions- bzw. Stoß-Theorie ist tatsächlich elementar einfach, die realistische Umsetzung natürlich tricky.
    Ca, 30 zu 70, wie üblich, ich arbeite dran.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    jo - die von dir verwendete Formel für den schiefen elastischen Stoss ist tatsächlich einfach: :thumbup:

    C#-Quellcode

    1. Vector v11 = 2F * ((m1 * v1) + (m2 * v2)) / (m1 + m2) - v1;
    2. Vector v22 = 2F * ((m1 * v1) + (m2 * v2)) / (m1 + m2) - v2;
    Wie du das aber dem Wiki-Artikel entnommen hast, ist mir unerfindlich. 8|



    Hmm - einen Nachteil sehe ich noch: Die Formel scheint falsch zu sein.
    Guck, ich hab bei dir Ball.Radius auf 50 erhöht, und dann einen TestStoss-Button eingeführt, der einen "zweidimensionalen" elastischen Stoss ausführt:

    C#-Quellcode

    1. private void btTestStoss_Click(object sender, EventArgs e) {
    2. var ball = new BallObject() { Location = new Vector(50, 50, 0), Speed = new Vector(.4f, 0, 0) };
    3. objects.Add(ball);
    4. ball = new BallObject() { Location = new Vector(350, 100, 0), Speed = new Vector(-.4f, 0, 0) };
    5. objects.Add(ball);
    6. }
    Wennde das laufen lässt siehste sofort, dass der Stoß falsch performt.
    Wie's aussieht gilt die Formel nur für den eindimensionalen Stoss.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @ErfinderDesRades Jou, das ist der zentale elastische Stoß.
    Den dezentralen (zweidimensionalen) reiche ich nach.
    Ich hab mal ab oben iwo gemeldet, dass unsere Diskussion in meinen neuen Stoß-Diskussions-Thread verschoben wird: Diskussion zum Thema Kollision und Reflexion - Elastischer Stoß
    Mal sehen, ob und wann das wird.
    =====
    Der Witz dabei besteht tatsächlich darin, die vielen Gleichungen für die einzelnen Komponenten als Gleichungen für die Komponenten eines Vektors zu verstehen
    und diese dann als Vektorgleichungen in den Quelltext zu schreiben, wobei die Klasse Vector um die entsprechenden Methoden ergänzt wird.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RodFromGermany“ ()

    @Thunderbolt hat die bisherige Diskussion hier angehängt - Danke.
    ====
    Ich muss mal einen Hilferuf loslassen.
    Die Quellen, die ich bisher geflöht habe, um den dezentralen elastischen Stoß zu bescheiben, scheinen nicht allgemein zu funktionieren (Radien, Massen) bzw. widersprechen sich:
    de.wikipedia.org/wiki/Sto%C3%9F_(Physik)
    physikerboard.de/topic,44001,-…lastischen-sto%C3%9F.html
    phynformatik.de/wordpress/wp-c…ds/2010/01/facharbeit.pdf
    Ich habe einige Spezialfälle eingebaut, um daran den Algorithmus zu testen.
    Wenn ein Fall funktioniert, funktioniert ein anderer nicht mehr.

    Wenn jemand von Euch noch eine Quelle mit der vektoriellen Darstellung des dezentralen elastischen Stoßes findet,
    bitte postet ihn hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Problem solved (glaubich):

    VB.NET-Quellcode

    1. Public Sub BallCollision(other As Ball)
    2. #If False Then
    3. 2-dimensionaler elastischer Stoss
    4. beim 1-D-Stoss tauschen 2 massegleiche Bälle ihre Geschwindigkeits-Vektoren.
    5. beim 2-D-Stoss zerlege die Vektoren in Kollisionsrichtung und orthogonal dazu. Die Kollisions-Vektoren werden ausgetauscht - orthogonales belassen
    6. Bei Masse-Ungleichheit ist statt des simplen Austausches die korrekte Formel für den 1-D-Stoss anzuwenden
    7. #End If
    8. Const toRadian = Math.PI / 180
    9. With other
    10. Dim collisionVector = .Location - Me.Location
    11. Dim rSum = .Radius + Radius : Dim squareDist = collisionVector.LengthSquared
    12. If rSum * rSum < squareDist Then Return ' keine Überlappung
    13. 'bei Überlappung kann auftreten, dass sie bereits (nach Kollision) auseinander-streben - dann keine Neuberechnung.
    14. Dim loc = Location + Speed * 0.001
    15. Dim loc2 = .Location + .Speed * 0.001
    16. If (loc2 - loc).LengthSquared > squareDist Then Return
    17. collisionVector.Normalize()
    18. Dim angle = Vector.AngleBetween(Speed, collisionVector) * toRadian
    19. Dim vColl = collisionVector * (Speed.Length * Math.Cos(angle))
    20. Dim vOrtho = Speed - vColl
    21. angle = Vector.AngleBetween(.Speed, collisionVector) * toRadian
    22. Dim vColl2 = collisionVector * (.Speed.Length * Math.Cos(angle))
    23. Dim vOrtho2 = .Speed - vColl2
    24. Speed = vOrtho + vColl2
    25. .Speed = vOrtho2 + vColl
    26. End With
    27. End Sub
    Also ich hab keine richtigen Tests gemacht - ich find nur, sieht plausibel aus.
    Wenn du den Ansatz richtig durchtesten könntest - gern auch um Masse-Berücksichtigung erweitert - wär supi :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @ErfinderDesRades Jou, das war es.
    Deine einfache Erklärung hat mir die Augen geöffnet.
    Ich hatte schon alles, bis auf die Übernahme der senkrechten Kompoenente.
    Dann werde ich mal die nunmehr aktuelle Version (Dezentraler Stoß gleicher Massen) im anderen Thread posten.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    guck, ich hab jetzt das Rudiment einer Physik-Engine angelegt:

    VB.NET-Quellcode

    1. Public Class PhysicEngine
    2. ''' <summary> collisionVector bezeichnet den Lage-Unterschied der Masse-Schwerpunkte zum Kollisions-Zeitpunkt</summary>
    3. Public Shared Sub Collision_2D(collisionVector As Vector, m1 As Double, ByRef v1 As Vector, m2 As Double, ByRef v2 As Vector)
    4. Const toRadian = Math.PI / 180
    5. collisionVector.Normalize()
    6. 'Vector-Zerlegungen in Kollisionsrichtung und Orthogonal dazu
    7. Dim angle = Vector.AngleBetween(v1, collisionVector)
    8. Dim vColl1 = collisionVector * (v1.Length * Math.Cos(angle * toRadian))
    9. Dim vOrtho1 = v1 - vColl1
    10. angle = Vector.AngleBetween(v2, collisionVector)
    11. Dim vColl2 = collisionVector * (v2.Length * Math.Cos(angle * toRadian))
    12. Dim vOrtho2 = v2 - vColl2
    13. 'Kollisions-Anteile eindimensional kollidieren, dann mit Orthogonal-Teil wiedervereinen
    14. Collision_1D(m1, vColl1, m2, vColl2)
    15. v1 = vOrtho1 + vColl1
    16. v2 = vOrtho2 + vColl2
    17. End Sub
    18. ''' <summary> eindimensionaler elastischer Stoss - v1 und v2 müssen genau gegenläufig sein </summary>
    19. Public Shared Sub Collision_1D(m1 As Double, ByRef v1 As Vector, m2 As Double, ByRef v2 As Vector)
    20. 'Formel aus Umstellung von https://de.wikipedia.org/wiki/Sto%C3%9F_(Physik)#Elastischer_Sto%C3%9F
    21. Dim weightedVectorSum = 2 * (m1 * v1 + m2 * v2) / (m1 + m2)
    22. v1 = weightedVectorSum - v1
    23. v2 = weightedVectorSum - v2
    24. End Sub
    25. End Class
    Ich kann dir übrigens die Vector-Structure der Wpf sehr empfehlen - und auch die anneren 2-D-Geschichten, wie Rect, Size, Point.
    Man muss aber die WindowBase.dll einbinden.
    Wenn das nicht wolle, und lieber Eigenbau, dann ists immer noch eine gute Architektur-Vorlage.

    ErfinderDesRades schrieb:

    'Vector-Zerlegungen in Kollisionsrichtung und Orthogonal dazu
    halte ich bei Dir für nicht optimal.
    Das geht alles mit Vector-Operationen, ein schnöder Math.Cos() ist da nicht erforderlich.
    Bei mir sieht das so aus:
    Spoiler anzeigen

    C#-Quellcode

    1. /// <summary>
    2. /// Zweidimensionaler elastischer Stoß,
    3. /// momentan mit gleicher Masse
    4. /// </summary>
    5. /// <param name="grn">Grüne Kugel beim Test</param>
    6. /// <param name="red">Rote Kugel beim Test</param>
    7. /// <returns></returns>
    8. public static bool CheckCrash(Sphaere grn, Sphaere red)
    9. {
    10. // https://de.wikipedia.org/wiki/Sto%C3%9F_(Physik)
    11. Vector dist = (red.Location - grn.Location);
    12. float distance = dist.Betrag();
    13. if (distance >= (grn.Radius + red.Radius))
    14. {
    15. return false;
    16. }
    17. float m1 = grn.Mass;
    18. float m2 = red.Mass;
    19. float m12 = m1 + m2;
    20. // Differenzvektor merken
    21. Vector n = dist.Clone();
    22. n.Norm();
    23. // parallele Richtungskomponente für Grün
    24. Vector vnGrn = Sphaere.ParallelComponent(n, grn.Speed);
    25. // parallele Richtungskomponente für Rot
    26. Vector vnRed = Sphaere.ParallelComponent(n, red.Speed);
    27. // senkrechte Richtungskomponenten
    28. Vector vEGrn = grn.Speed - vnGrn;
    29. Vector vERed = red.Speed - vnRed;
    30. #if false // ist noch falsch
    31. #if true
    32. Vector un1 = m1 * vnGrn + m2 * (2 * vnRed - vnGrn) / m12;
    33. Vector un2 = m2 * vnRed + m1 * (2 * vnGrn - vnRed) / m12;
    34. #else
    35. // wie beim zentralen Stoß
    36. Vector un1 = 2F * ((m1 * vnGrn) + (m2 * vnRed)) / (m1 + m2) - vnGrn;
    37. Vector un2 = 2F * ((m1 * vnGrn) + (m2 * vnRed)) / (m1 + m2) - vnRed;
    38. #endif
    39. #endif
    40. grn.Speed = vnRed + vEGrn;
    41. red.Speed = vnGrn + vERed;
    42. return true;
    43. }
    44. /// <summary>
    45. /// Berechnung der parallelen Richtungskomponenten nach dem Stoß
    46. /// </summary>
    47. /// <param name="n"></param>
    48. /// <param name="v"></param>
    49. /// <returns></returns>
    50. private static Vector ParallelComponent(Vector n, Vector v)
    51. {
    52. float factor = (n * v) / n.Betrag();
    53. return factor * n;
    54. }

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Mir scheint dein Paralellisierungs-Dingens fehlerhaft - bei mir tuts folgendes:

    VB.NET-Quellcode

    1. ''' <summary> Gibt den Teil von v1 zurück, der paralell zu vNorm verläuft - Achtung!: vNorm muss normalisiert sein (Länge 1 haben) </summary>
    2. <Extension>
    3. Public Function ParalellPartTo(v1 As Vector, vNorm As Vector) As Vector
    4. Return (vNorm * v1) * vNorm
    5. End Function
    Schickt man viele Bälle in kurzer Zeit los, ergeben sich lustige 2-atomige Molekülkonstellationen, die auch befähigt sind, das Spielfeld zu verlassen. Auch können neue Moleküle durch knappen 2-Ball-Wand-Kontakt entstehen.
    Ich hab noch späßleshalber ne Impulskontrolle beim timer1_tick eingebaut:

    C#-Quellcode

    1. double ActualImpulse = 0;
    2. for (int i = 0; i < this.Spheres.Count; i++)
    3. {
    4. ActualTotalImpulse += this.Spheres[i].Mass * this.Spheres[i].Speed.Betrag();
    5. //...
    6. double ImpulseRatio = ActualTotalImpulse / TotalImpulse;
    7. if (ImpulseRatio < .8 || ImpulseRatio > 1.2)
    8. timer1.Stop();

    TotalImpulse wird bei der Sphärenerzeugung erhöht. Bei Kollisionen kommt es immer wieder zu starken Schwankungen. Falls das was für den weiteren Fortschritt zu bedeuten hat.

    btw: So ganz orthogonal ist der OrthogonalCrash aufgrund der Startposition von Sphäre1 nicht. Setzt man diese auf new Vector(x1, y1, 0);, dann passt es.

    EDIT @RodFromGermany: Durch die Impulskontrolle ergab sich z.B., dass beim ParallelCrash (Abstand 0,8) vor der Kollision Sphäre1 einen Impuls von 1, S2 hingegen 0 hat. Logisch. Nach dem Aufprall hingegen: S1: 0,4; S2: 0,9
    Da irgendwann mal das Wort Impulserhaltungssatz fiel ...
    Bilder
    • MolecularMovements.png

      3,42 kB, 519×400, 100 mal angesehen
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „VaporiZed“ ()

    @VaporiZed Jou. Das steht schon im 1. Post im anderen Thread: ;)

    RodFromGermany schrieb:

    Mit dem Button Next wird eine neue Kugel ins Spiel gebracht. Immer an derselben Position, aber mit Zufalls-Geschwindigkeiten.
    Hierbei wird momentan nicht getestet, ob sich an der Einfügeposition eine Kugel befindet, da kann also Unsinn passieren.
    Ich werd dies mal höher priorisieren.
    Belassen wir es zunächst bei gleichen Massen bzw. Masse Unendlich für die Wand und bringen das Billard ordentlich zum Laufen...

    @VaporiZed Deine Impulsrechnung kann ich leider nicht nachvollziehen, bei mir kommt da stets Null oder eine "Gammelnull" raus, überprüf mal Deine Impuls-Mathematik.
    Die Aussage lautet: Summe der Impulse (der Stoßkandidaten) vorher ist gleich der Summe der Impulse nachher.
    Code

    C#-Quellcode

    1. public static bool CheckCrash(Sphaere grn, Sphaere red)
    2. {
    3. // https://de.wikipedia.org/wiki/Sto%C3%9F_(Physik)
    4. Vector dist = (red.Location - grn.Location);
    5. float distance = dist.Betrag();
    6. if (distance >= (grn.Radius + red.Radius))
    7. {
    8. return false;
    9. }
    10. float m1 = grn.Mass;
    11. float m2 = red.Mass;
    12. float m12 = m1 + m2;
    13. Vector impulsA1 = m1 * grn.Speed;
    14. Vector impulsA2 = m2 * red.Speed;
    15. impulsA1 += impulsA2;
    16. Console.WriteLine("Impuls 1: " + impulsA1);
    17. Console.WriteLine("Impuls 2: " + impulsA2);
    18. // Differenzvektor merken
    19. Vector n = dist.Clone();
    20. n.Norm();
    21. // parallele Richtungskomponente für Grün
    22. Vector vnGrn = Sphaere.ParallelComponent(n, grn.Speed);
    23. // parallele Richtungskomponente für Rot
    24. Vector vnRed = Sphaere.ParallelComponent(n, red.Speed);
    25. // senkrechte Richtungskomponenten
    26. Vector vEGrn = grn.Speed - vnGrn;
    27. Vector vERed = red.Speed - vnRed;
    28. #if false // true // ist noch falsch
    29. #if true //false //
    30. Vector un1 = m1 * vnGrn + m2 * (2 * vnRed - vnGrn) / m12;
    31. Vector un2 = m2 * vnRed + m1 * (2 * vnGrn - vnRed) / m12;
    32. #else
    33. // wie beim zentralen Stoß
    34. grn.Speed = 2F * ((m1 * vnGrn) + (m2 * vnRed)) / (m1 + m2) - vEGrn;
    35. red.Speed = 2F * ((m1 * vnGrn) + (m2 * vnRed)) / (m1 + m2) - vERed;
    36. #endif
    37. #else
    38. // dies geht
    39. grn.Speed = vnRed + vEGrn;
    40. red.Speed = vnGrn + vERed;
    41. #endif
    42. Vector impulsB1 = m1 * grn.Speed;
    43. Vector impulsB2 = m2 * red.Speed;
    44. impulsB1 += impulsB2;
    45. Console.WriteLine("Impuls 3: " + impulsB1);
    46. Console.WriteLine("Impuls 4: " + impulsB2);
    47. Vector delta = impulsA1 - impulsB1;
    48. float betrag = delta.Betrag();
    49. Console.WriteLine("Impuls-Betrag: " + betrag);
    50. return true;
    51. }
    Ausgabe

    Quellcode

    1. Impuls 1: {X=-0,006776392, Y=0,8269069, Z=0}
    2. Impuls 2: {X=0,6971545, Y=0,7199919, Z=0}
    3. Impuls 3: {X=-0,006776392, Y=0,8269069, Z=0}
    4. Impuls 4: {X=-0,4982327, Y=-0,1695174, Z=0}
    5. Impuls-Betrag: 0
    6. Impuls 1: {X=1,523277, Y=-0,9458271, Z=0}
    7. Impuls 2: {X=0,3771891, Y=-0,5993356, Z=0}
    8. Impuls 3: {X=1,523277, Y=-0,9458271, Z=0}
    9. Impuls 4: {X=0,8923351, Y=-0,8559306, Z=0}
    10. Impuls-Betrag: 0
    11. Impuls 1: {X=0,3341638, Y=0,5675088, Z=0}
    12. Impuls 2: {X=0,7820206, Y=0,6240089, Z=0}
    13. Impuls 3: {X=0,3341638, Y=0,5675088, Z=0}
    14. Impuls 4: {X=0,5560282, Y=-0,3016031, Z=0}
    15. Impuls-Betrag: 0
    16. Impuls 1: {X=0,1394852, Y=-1,086321, Z=0}
    17. Impuls 2: {X=0,6309415, Y=-0,0898965, Z=0}
    18. Impuls 3: {X=0,1394852, Y=-1,086321, Z=0}
    19. Impuls 4: {X=-0,6508538, Y=-0,576822, Z=0}
    20. Impuls-Betrag: 0
    21. Impuls 1: {X=-1,124262, Y=0,2283351, Z=0}
    22. Impuls 2: {X=-0,6260296, Y=0,3978525, Z=0}
    23. Impuls 3: {X=-1,124262, Y=0,228335, Z=0}
    24. Impuls 4: {X=-0,5955275, Y=-0,1747007, Z=0}
    25. Impuls-Betrag: 1,490116E-08
    26. Impuls 1: {X=1,543189, Y=-0,2791086, Z=0}
    27. Impuls 2: {X=0,8923351, Y=-0,8559306, Z=0}
    28. Impuls 3: {X=1,543189, Y=-0,2791086, Z=0}
    29. Impuls 4: {X=1,497606, Y=-0,1134716, Z=0}
    30. Impuls-Betrag: 2,980232E-08
    31. Impuls 1: {X=0,3068704, Y=1,272148, Z=0}
    32. Impuls 2: {X=0,5287347, Y=0,4030357, Z=0}
    33. Impuls 3: {X=0,3068704, Y=1,272148, Z=0}
    34. Impuls 4: {X=-0,2621824, Y=0,4863459, Z=0}
    35. Impuls-Betrag: 2,980232E-08
    36. Impuls 1: {X=-0,7447563, Y=0,3438618, Z=0}
    37. Impuls 2: {X=0,04558267, Y=-0,1656369, Z=0}
    38. Impuls 3: {X=-0,7447563, Y=0,3438618, Z=0}
    39. Impuls 4: {X=0,1549131, Y=0,06893967, Z=0}
    40. Impuls-Betrag: 2,980232E-08
    41. Impuls 1: {X=1,054583, Y=0,3438618, Z=0}
    42. Impuls 2: {X=0,1549131, Y=0,06893967, Z=0}
    43. Impuls 3: {X=1,054582, Y=0,3438618, Z=0}
    44. Impuls 4: {X=0,9135231, Y=0,1818103, Z=0}
    45. Impuls-Betrag: 1,192093E-07
    46. Impuls 1: {X=-0,9285533, Y=-0,8992733, Z=0}
    47. Impuls 2: {X=-1,497606, Y=-0,1134716, Z=0}
    48. Impuls 3: {X=-0,9285533, Y=-0,8992733, Z=0}
    49. Impuls 4: {X=-0,4749318, Y=-1,53622, Z=0}
    50. Impuls-Betrag: 5,960464E-08

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „RodFromGermany“ ()

    Könnte man vielleicht die iterative Berechnung durch eine kontinuierliche ersetzen? Also dass man einen mathematischen Ansatz findet, um den Pfad jeder Kugel und deren Interaktion durch kontinuierliche Funktionen darzustellen: Die Bewegungen sind einfache Geradengleichungen und alle Kollisionen lassen sich dadurch exakt bestimmen, dass ​sqrt((x_2 - x_1)^2 + (y_2 - y_1)^2) = 2 * r sein muss. Mit diesem Ansatz könnte man doch alle Vorgänge auf dem Feld in einer Genauigkeit beschreiben, welche nur durch die Präzision der verwendeten Datentypen beschränkt ist, oder übersehe ich da was?
    @nafets Das ist korrekt, an diesem Problem arbeite ich gerade.
    Herangehensweise:
    Für zwei stoßende Probanden wird der exakte Zeitpunkt des Stoßes berechnet.
    Es wird die exakte Reflexion berechnet und die Position am Ende des aktuellen Zeit-Intervalls eingenommen.
    Für alle im aktuellen Intervall stoßenden Probanden wird die relative Stoßzeit berechnet und die Probanden in dieser Reihenfolge abgearbeitet.
    Damit sind allerdings Dreifach-Stöße noch nicht korrekt behandelt, was sich aber durch kleinere Zeitscheiben realisieren ließe (niedrige Priorität).

    @VB3-Guru Danke für die Info.
    Dieses Forum ist ja echt nervig zu lesen. ;(
    Der Quellcode ist noch echt aus VB3-Zeiten, die beste Zeile, die ich beim Überfliegen gefunden habe, ist:

    Visual Basic-Quellcode

    1. Button3.Text = RunStop(Timer1.Enabled ^ 2)
    Ich werd mal probieren, die relevante Prozedur CalcPath() zu übertragen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RodFromGermany“ ()

    Meine Idee ging eher in die Richtung, die Simulation komplett von der Darstellung zu entkoppeln und einfach nach und nach den Definitionsbereich der Funktionen zu erweitern (immer alle Stöße mit deren Auswirkungen bis zum Zeitpunkt t_x bestimmen und Funktionen dafür aufstellen, dann bei der Darstellung einfach den aktuellen Zeitpunkt in die Funktionen für die Kugeln einsetzen). Dreifachstöße sind bei diesem Ansatz zwar extrem unwahrscheinlich, dieses Problem könnte man aber genausogut allgemeingültig für n-fach-Stöße lösen und einarbeiten.

    @VB3-Guru
    Ich könnte falsch liegen, aber sind Moshpits nicht die komplett falsche Richtung? Die haben ja nichts mit elastischen Stößen zu tun, sondern in erster Linie mit Gruppendynamik von Menschen.
    @VB3-Guru Es sieht so aus, als ob im Code rein elektrische Kräfte abgehandelt werden.
    Wenn die Elementarladung auf 0 gesetzt wird, passiert nix, die Initialkugel schwebt linear aus dem Raum heraus und feddich.
    Die Bewegung folgt der Newtonschen Gleichung über Beschleunigung und Kraft.
    Hat also mit unserem Problem hier nix zu tun.
    Sorry.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!