Kollision zweier Kugeln (2D): Unterschied zwischen den Versionen

aus GlossarWiki, der Glossar-Datenbank der Fachhochschule Augsburg
Kowa (Diskussion | Beiträge)
Kowa (Diskussion | Beiträge)
Keine Bearbeitungszusammenfassung
 
(20 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
{{In Bearbeitung}}
{{Qualität
{{Qualität
|correctness        = 0
|correctness        = 1
|extent              = 0
|extent              = 1
|numberOfReferences  = 1
|numberOfReferences  = 1
|qualityOfReferences = 3
|qualityOfReferences = 3
|conformance        = 5
|conformance        = 5
}}
}}
{{In Bearbeitung}}
[[Datei:KollisionZweiKugeln1.png|miniatur|375px|Kollision zweier Kugeln]]
[[Datei:KollisionZweiKugeln2.png|miniatur|461px|Der Tunnel-Effekt]]


==Grundannahmen==
==Grundannahmen==


Ein Ball-Objekt <code>b</code> habe folgende Attribute:
Es sei ein zweidimensionales Ball-Objekt <code>b</code> gegeben, das folgende Attribute habe:


* <code>x</code>, <code>y<code>: Position (Einheit: Pixel)
* <code>x</code>, <code>y</code>: Position (Einheit: Pixel)
* <code>vx</code>, <code>vy<code>: Geschwindigkeit in $x$- und $y$-Richtung (Einheit: Pixel/s)
* <code>vx</code>, <code>vy</code>: Geschwindigkeit in $x$- und $y$-Richtung (Einheit: Pixel/s)
* <code>ax</code>, <code>ay<code>: Beschleunigung in $x$- und $y$-Richtung  (Einheit: Pixel/s)
* <code>r</code>: Radius (Einheit: Pixel)
* <code>r</code>: Radius (Einheit: Pixel)
* <code>m</code>: Masse (die Einheit ist irrelevant, sie muss nur für alle Bälle dieselbe sein)
* <code>m</code>: Masse (die Einheit ist irrelevant, sie muss nur für alle Bälle dieselbe sein)


Die Berechnung der Position aller im System vorhandener Bälle erfolgt <code>fps</code>
Die [[Frequenz]] der Neuberechnung der Positionen aller im System vorhandener Bälle sei <code>f</code>,
(frames per second) mal pro Sekunde. Wenn es zu keiner Kollision kommt, wird
{{dh}}, die Positionen werden <code>f</code> mal pro Sekunde neuberechnet. Wenn es zu keiner Kollision kommt, wird
der Ball um <code>vx/fps</code> bzw. <code>vy/fps<code> Pixel in
der Ball um <code>vx/f</code> bzw. <code>vy/f</code> Pixel in
$x$- bzw. $y$-Richtung verschoben:
$x$- bzw. $y$-Richtung verschoben:


<source lang="javascript">
<source lang="javascript">
   b.x += b.vx/fps;
   b.x += b.vx/f;
   b.y += b.vy/fps;
   b.y += b.vy/f;
</source>
</source>


Anschließend wird der Beschleunigungsvektor analog angepasst:
Je höher die Frequent <code>f</code> ist, desto genauer wird die Bewegungsbahn der Bälle simuliert.
 
<!--
Im Folgenden seinen $s_1 = \begin{pmatrix}s_{1x}\\s_{1y}\end{pmatrix}$ und $s_2 = \begin{pmatrix}s_{2x}\\s_{2y}\end{pmatrix}$ die Startpositionen
zweier Balle und $v_1 = \begin{pmatrix}v_{1x}\\v_{1y}\end{pmatrix}$ und $v_2 = \begin{pmatrix}v_{2x}\\v_{2y}\end{pmatrix}$ die zugehörigen
Geschwindigkeitsvektoren.-->
Im Folgenden seinen $s_1 = (s_{1x},s_{1y})$ und $s_2 = (s_{2x},s_{2y})$ die Startpositionen
zweier Balle und $v_1 = (v_{1x},v_{1y})$ und $v_2 = (v_{2x},v_{2y})$ die zugehörigen
Geschwindigkeitsvektoren.


<source lang="javascript">
Es gilt also, dass sich die beiden Bälle zu Zeitpunkt $t_0$ an den Positionen $s_1$ und $s_2$ befinden.
  b.vx += b.ax/fps;
Eine Sekunde später, {{dh}} zum Zeitpunkt $t_0+1$ befinden sich sich an den Positionen $s_1+v_1$ und $s_2+v_2$, sofern sie nicht kollidieren.
  b.vy += b.ay/fps;
Wenn die Neuberechnung mit einer [[Frequenz]] $f$ Hz erfolgt, {{dh}}, wenn die [[Periodendauer]] $t = 1/f$ beträgt, dann
</source>
befinden sich die Bälle nach der Berechnung an den Positionen $s_1+tv_1$ und $s_2+tv_2$, sofern sie nicht kollidieren.


Je höher die Framrate ist, desto genauer wird die Bewegungsbahn der Bälle simuliert.
In Folgenden wird stets der Fall $t=1$ angenommen. Alle Aussagen, die für einen ''beliebigen'' Geschwindigkeitsvektor
$v$ gelten, gelten dann natürlich auch für $v' := sv$, wobei $s$ ein beliebiger skalarer Wert sei.


==[[A-posteriori-Kollisionserkennung]] von zwei Kugeln==
==[[A-posteriori-Kollisionserkennung]] von zwei Kugeln==
Beispiel: [https://glossar.hs-augsburg.de/beispiel/tutorium/2018/ball/WK_Ball02/web/index04c.html WK_Ball02: index40c.html]
<source lang="javascript">
const  EPSILON = Number.EPSILON;


<source lang="javascript">
function collisionCircleCircle(p_c1, p_c2)
  function collisionBallBall(p_b1, p_b2)
{ // l_n: Normalenvektor (Verbindung zwischen den beiden Kugeln)
  {
  let l_nx = p_c2.x - p_c1.x;
    // l_n: Normalenvektor (Verbindung zwischen den beiden Kugelnn)
  let l_ny = p_c2.y - p_c1.y;
    var l_nx = p_b2.getX() - p_b1.getX();
 
    var l_ny = p_b2.getY() - p_b1.getY();
  // Abstand der beiden Kugeln
  let l_dist = Math.sqrt(l_nx * l_nx + l_ny * l_ny);
    
    
    // Abstand der beiden Kugeln
  // Die Kugeln dürfen sich nicht an derselben Stelle befinden,
     var l_dist = Math.sqrt( l_nx * l_nx + l_ny * l_ny );
  // weil sie sonst nicht entlang der nicht-existenten Normalen
  // auseinandergezogen werden können.
  // Dieser Fall sollte nur sehr selten eintreten (z.B. wenn eine
  // neue Kugel genau an der Stelle einer existenten Kugel erstellt wird).
  if (l_dist < EPSILON)
  { p_c2.x = p_c2.x + p_c2.r;
    l_nx += p_c2.r;
     l_dist = Math.sqrt(l_nx * l_nx + l_ny * l_ny);
  }
    
    
    // Die Kugeln dürfen sich nicht an derselben Stelle befinden,
  // Kugeln kollidieren, wenn der Abstand kleiner gleich der Summe
     // weil sie sonst nicht entlang der nicht-existenten Normalen
  // der Radien beider Kugeln ist.
     // auseinandergezogen werden können.
  if (l_dist <= p_c1.r + p_c2.r)
     // Dieser Fall sollte nur sehr selten eintreten (z.B. wenn eine
  { // Normalenvektor wird normalisiert: |l_n| = 1
     // neue Kugel genau an der Stelle einer existenten Kugel erstellt wird).
     l_nx /= l_dist;
     if (l_dist < EPSILON)
    l_ny /= l_dist;
     {
   
      p_b2.setX(p_b2.getX()+ p_b2.getR());
    // Tangentialvektor (senkrecht zu Normalenvektor, zwischen beiden Kugeln)
      l_nx += p_b2.getR();
    let l_tx =  l_ny;
      l_dist = Math.sqrt( l_nx * l_nx + l_ny * l_ny );
    let l_ty = -l_nx;
     };
   
     // Summe der Massen beider Kugeln
    let l_sm1m2 = p_c1.m + p_c2.m;
   
     // Überlappung der beiden Kugeln
    let l_overlap = (p_c1.r + p_c2.r) - l_dist;
   
     // Verschieben der beiden Kugeln entlang der Normalen,
    // so dass sie sich nicht mehr überlappen!
    // Die Massen werden berücksichtigt. Schwerere Kreise werden
    // weniger weit verschoben.
     l_overlap += 2;    /* fight penetration */
     l_overlap *= 1.001; /* fight penetration */
    p_c1.x = p_c1.x - l_nx * l_overlap * (p_c2.m / l_sm1m2);
    p_c1.y = p_c1.y - l_ny * l_overlap * (p_c2.m / l_sm1m2);
    p_c2.x = p_c2.x + l_nx * l_overlap * (p_c1.m / l_sm1m2);
     p_c2.y = p_c2.y + l_ny * l_overlap * (p_c1.m / l_sm1m2);
      
      
     // Kugeln kollidieren, wenn der Abstand kleiner gleich der Summe
     // Zerlegung der Geschwindigkeitsvektoren in Normalen- und
    // der Radien beider Kugeln ist.
    // Tangentialanteil: v=sn*n+st*t, wobei
    if (l_dist <= p_b1.getR() + p_b2.getR())
    // v Vektor, n Normalenvektor, t Tagentialvektor und
    {
    // sn, st zwei skalare Werte sind.
      // Normalenvektor wird normalisiert: |l_n| = 1
    // Es gilt: v*n = sn*(n*n)+st*(t*n) = sn, da t*n=0 und n*n = 1
      l_nx /= l_dist;
    // Es gilt: v*t = sn*(n*t)+st*(t*t) = st, da t*n=0 und t*t = 1
      l_ny /= l_dist;
    // Also ist: sn = v*n und st=v*t
       
   
      //Tangentialvektor (senkrecht zu Normalenvektor, zwischen beiden Kugeln)
    // Ball 1: Zerlegung des Geschwindigkeitsvektors in n- und t-Anteil
      var l_tx = l_ny;
    let l_sn1 = l_nx * p_c1.vx + l_ny * p_c1.vy;
      var l_ty = -l_nx;
    let l_st1 = l_tx * p_c1.vx + l_ty * p_c1.vy;
       
   
      // Summe der Massen beider Kugeln
    let l_n1x = l_nx * l_sn1; // Normalenvektor-Anteil von p_c1.vx
      var l_sm1m2 = p_b1.getMass() + p_b2.getMass();
    let l_n1y = l_ny * l_sn1; // Normalenvektor-Anteil von p_c1.vy
 
   
      // Überlappung der beiden Kugeln
    let l_t1x = l_tx * l_st1; // Tangentialvektor-Anteil von p_c1.vx
      var l_overlap = ( p_b1.getR() + p_b2.getR() ) - l_dist;
    let l_t1y = l_ty * l_st1; // Tangentialvektor-Anteil von p_c1.vy
 
   
      // Verschieben der beiden Kugeln entlang der Normalen,
    // Ball 2: Zerlegung des Geschwindigkeitsvektors in n- und t-Anteil
      // so dass sie sich nicht mehr überlappen!
    let l_sn2 = l_nx * p_c2.vx + l_ny * p_c2.vy;
      p_b1.setX(p_b1.getX() - l_nx * l_overlap * (p_b2.getMass()/l_sm1m2) * (1+EPSILON));
    let l_st2 = l_tx * p_c2.vx + l_ty * p_c2.vy;
      p_b1.setY(p_b1.getY() - l_ny * l_overlap * (p_b2.getMass()/l_sm1m2) * (1+EPSILON));
   
      p_b2.setX(p_b2.getX() + l_nx * l_overlap * (p_b1.getMass()/l_sm1m2) * (1+EPSILON));
    let l_n2x = l_nx * l_sn2; // Normalenvektor-Anteil von p_c2.vx
      p_b2.setY(p_b2.getY() + l_ny * l_overlap * (p_b1.getMass()/l_sm1m2) * (1+EPSILON));
    let l_n2y = l_ny * l_sn2; // Normalenvektor-Anteil von p_c2.vy
 
   
      // Zerlegung der Geschwindigkeitsvektoren in Normalen- und  
    let l_t2x = l_tx * l_st2; // Tangentialvektor-Anteil von p_c2.vx
      // Tangentialanteil: v=sn*n+st*t, wobei  
    let l_t2y = l_ty * l_st2; // Tangentialvektor-Anteil von p_c2.vy
      // v Vektor, n Normalenvektor, t Tagentialvektor und
   
      // sn, st zwei skalare Werte sind.
    // Der Impulserhaltungssatz
      // Es gilt: v*n = sn*(n*n)+st*(t*n) = sn, da t*n=0 und n*n = 1
    //  m1*v1 + m2*v2 = m1*v1' + m2*v2'
      // Es gilt: v*t = sn*(n*t)+st*(t*t) = st, da t*n=0 und t*t = 1
    //  (wobei m1, m2 = Massen der Körper
      // Also ist: sn = v*n und st=v*t
    //    und v1, v2, v1', v2' die Geschwindigkeiten)
 
    // und der Energieerhaltungssatz
      // Ball 1: Zerlegung des Geschwindigkeitsvektors in n- und t-Anteil
    //  0,5*m1*v1² + 0,5*m2*v2² = 0,5*m1*v1'² + 0,5*m2*v2'²
      var l_sn1 = l_nx * p_b1.getVx() + l_ny * p_b1.getVy();
    // führen nach einfachen mathematischen Umformungen zu
      var l_st1 = l_tx * p_b1.getVx() + l_ty * p_b1.getVy();
    // folgenden Beziehungen (für den eindimensionalen Fall):
 
    //  v1' = 2*(m1*v1+m2*v2)/(m1+m2) - v1
      var l_n1x = l_nx * l_sn1; // Normalenvektor-Anteil von p_b1.getVx()
    //  v2' = 2*(m1*v1+m2*v2)/(m1+m2) - v2
      var l_n1y = l_ny * l_sn1;
    //  2*(m1*v1+m2*v2)/(m1+m2) ist die Geschwindigkeit des
     
    //                          gemeinsamen Schwerpunktes
      var l_t1x = l_tx * l_st1; // Tangentialvektor-Anteil von p_b1.getVx()
    //                          (center of gravity).  
      var l_t1y = l_ty * l_st1;
    // Im zweidimensionalen Fall gilt, dass die Kollision entlang
       
    // der Normalen erfolgt. Die tangentialen Anteile der der
      // Ball 2: Zerlegung des Geschwindigkeitsvektors in n- und t-Anteil
    // Bewegungsrichtungen werden unverändert übernommen.
      var l_sn2 = l_nx * p_b2.getVx() + l_ny * p_b2.getVy();
   
      var l_st2 = l_tx * p_b2.getVx() + l_ty * p_b2.getVy();
    let l_vcgx = 2*(p_c1.m * l_n1x + p_c2.m * l_n2x) / l_sm1m2;
           
    let l_vcgy = 2*(p_c1.m * l_n1y + p_c2.m * l_n2y) / l_sm1m2;
      var l_n2x = l_nx * l_sn2; // Normalenvektor-Anteil von p_b2.getVx()
   
      var l_n2y = l_ny * l_sn2;
    p_c1.vx = l_vcgx - l_n1x + l_t1x;
         
    p_c1.vy = l_vcgy - l_n1y + l_t1y;
      var l_t2x = l_tx * l_st2; // Tangentialvektor-Anteil von p_b2.getVx()
    p_c2.vy = l_vcgx - l_n2x + l_t2x;
      var l_t2y = l_ty * l_st2;
    p_c2.vy = l_vcgy - l_n2y + l_t2y;
           
   
      // Der Impulserhaltungssatz
    //// Alternative Berechnung:
      //  m1*v1 + m2*v2 = m1*u1 + m2*u2
    // Differenz der Massen beide Kugeln
      //  (wobei m1, m2 = Massen der Körper  
    // let l_dm2m1 = p_c2.m - p_c1.m;
      //    und v1, v2, u1, u2 die Geschwindigkeiten)
    // p_c1.vx = (l_n2x*p_c2.m*2-l_n1x*l_dm2m1)/l_sm1m2 + l_t1x;
      // und der Energieerhaltsungssatz
    // p_c1.vy = (l_n2y*p_c2.m*2-l_n1y*l_dm2m1)/l_sm1m2 + l_t1y;
      //  0,5*m1*v1² + 0,5*m2*v2² = 0,5*m1*u1² + 0,5*m2*u2²
    // p_c2.vx = (l_n1x*p_c1.m*2+l_n2x*l_dm2m1)/l_sm1m2 + l_t2x;
      // führen nach einfachen mathematischen Umformungen zu
    // p_c2.vy =(l_n1y*p_c1.m*2+l_n2y*l_dm2m1)/l_sm1m2 + l_t2y;
      // folgenden Beziehungen (für den eindimensionalen Fall):
    return true;
      //  u1 = 2*(m1*v1+m2*v2)/(m1+m2) - v1
      //  u2 = 2*(m1*v1+m2*v2)/(m1+m2) - v2
      //  2*(m1*v1+m2*v2)/(m1+m2) ist die Geschwindigkeit des  
      //                          gemeinsamen Schwerpunktes.
      // Im zweidimensionalen Fall gilt, dass die Kollision entlang
      // der Normalen erfolgt. Die tangentialen Anteile der der  
      // Bewegungsrichtungen werden unverändert übernommen.
       
      var l_vspx = 2*(p_b1.getMass()*l_n1x+p_b2.getMass()*l_n2x)/l_sm1m2;
      var l_vspy = 2*(p_b1.getMass()*l_n1y+p_b2.getMass()*l_n2y)/l_sm1m2;
       
      p_b1.setVx(l_vspx - l_n1x + l_t1x);
      p_b1.setVy(l_vspy - l_n1y + l_t1y);
      p_b2.setVx(l_vspx - l_n2x + l_t2x);
      p_b2.setVy(l_vspy - l_n2y + l_t2y);
       
      //// Alternative Berechnung:
      // Differenz der Massen beide Kugeln
      // var l_dm2m1 = p_b2.getMass() - p_b1.getMass();
      // p_b1.setVx((l_n2x*p_b2.getMass()*2-l_n1x*l_dm2m1)/l_sm1m2 + l_t1x);
      // p_b1.setVy((l_n2y*p_b2.getMass()*2-l_n1y*l_dm2m1)/l_sm1m2 + l_t1y);
      // p_b2.setVx((l_n1x*p_b1.getMass()*2+l_n2x*l_dm2m1)/l_sm1m2 + l_t2x);
      // p_b2.setVy((l_n1y*p_b1.getMass()*2+l_n2y*l_dm2m1)/l_sm1m2 + l_t2y);
   }
   }
  else
  { return false; }
}
}
</source>
</source>


==[[A-priori-Kollisionserkennung]] von zwei Kugeln==
==[[A-priori-Kollisionserkennung]] von zwei Kugeln==
 
[[Datei:KollisionZweiKugeln1.png|miniatur|375px|Kollision zweier Kugeln]]
[[Datei:KollisionZweiKugeln2.png|miniatur|461px|Der Tunnel-Effekt]]
==Quellen==
==Quellen==
<references/>
<references/>

Aktuelle Version vom 23. November 2018, 17:52 Uhr

Dieser Artikel wird derzeit von einem Autor gründlich bearbeitet. Die Inhalte sind daher evtl. noch inkonsistent.

Dieser Artikel erfüllt die GlossarWiki-Qualitätsanforderungen nur teilweise:

Korrektheit: 1
(nur rudimäntär überprüft)
Umfang: 1
(zu gering)
Quellenangaben: 1
(fehlen großteils)
Quellenarten: 3
(gut)
Konformität: 5
(ausgezeichnet)

Grundannahmen

Es sei ein zweidimensionales Ball-Objekt b gegeben, das folgende Attribute habe:

  • x, y: Position (Einheit: Pixel)
  • vx, vy: Geschwindigkeit in $x$- und $y$-Richtung (Einheit: Pixel/s)
  • r: Radius (Einheit: Pixel)
  • m: Masse (die Einheit ist irrelevant, sie muss nur für alle Bälle dieselbe sein)

Die Frequenz der Neuberechnung der Positionen aller im System vorhandener Bälle sei f, d. h., die Positionen werden f mal pro Sekunde neuberechnet. Wenn es zu keiner Kollision kommt, wird der Ball um vx/f bzw. vy/f Pixel in $x$- bzw. $y$-Richtung verschoben:

  b.x += b.vx/f;
  b.y += b.vy/f;

Je höher die Frequent f ist, desto genauer wird die Bewegungsbahn der Bälle simuliert.

Im Folgenden seinen $s_1 = (s_{1x},s_{1y})$ und $s_2 = (s_{2x},s_{2y})$ die Startpositionen zweier Balle und $v_1 = (v_{1x},v_{1y})$ und $v_2 = (v_{2x},v_{2y})$ die zugehörigen Geschwindigkeitsvektoren.

Es gilt also, dass sich die beiden Bälle zu Zeitpunkt $t_0$ an den Positionen $s_1$ und $s_2$ befinden. Eine Sekunde später, d. h. zum Zeitpunkt $t_0+1$ befinden sich sich an den Positionen $s_1+v_1$ und $s_2+v_2$, sofern sie nicht kollidieren. Wenn die Neuberechnung mit einer Frequenz $f$ Hz erfolgt, d. h., wenn die Periodendauer $t = 1/f$ beträgt, dann befinden sich die Bälle nach der Berechnung an den Positionen $s_1+tv_1$ und $s_2+tv_2$, sofern sie nicht kollidieren.

In Folgenden wird stets der Fall $t=1$ angenommen. Alle Aussagen, die für einen beliebigen Geschwindigkeitsvektor $v$ gelten, gelten dann natürlich auch für $v' := sv$, wobei $s$ ein beliebiger skalarer Wert sei.

A-posteriori-Kollisionserkennung von zwei Kugeln

Beispiel: WK_Ball02: index40c.html

const  EPSILON = Number.EPSILON;

function collisionCircleCircle(p_c1, p_c2)
{ // l_n: Normalenvektor (Verbindung zwischen den beiden Kugeln)
  let l_nx = p_c2.x - p_c1.x;
  let l_ny = p_c2.y - p_c1.y;
  
  // Abstand der beiden Kugeln
  let l_dist = Math.sqrt(l_nx * l_nx + l_ny * l_ny);
  
  // Die Kugeln dürfen sich nicht an derselben Stelle befinden,
  // weil sie sonst nicht entlang der nicht-existenten Normalen
  // auseinandergezogen werden können.
  // Dieser Fall sollte nur sehr selten eintreten (z.B. wenn eine
  // neue Kugel genau an der Stelle einer existenten Kugel erstellt wird).
  if (l_dist < EPSILON)
  { p_c2.x = p_c2.x + p_c2.r;
    l_nx += p_c2.r;
    l_dist = Math.sqrt(l_nx * l_nx + l_ny * l_ny);
  }
  
  // Kugeln kollidieren, wenn der Abstand kleiner gleich der Summe
  // der Radien beider Kugeln ist.
  if (l_dist <= p_c1.r + p_c2.r)
  { // Normalenvektor wird normalisiert: |l_n| = 1
    l_nx /= l_dist;
    l_ny /= l_dist;
    
    // Tangentialvektor (senkrecht zu Normalenvektor, zwischen beiden Kugeln)
    let l_tx =  l_ny;
    let l_ty = -l_nx;
    
    // Summe der Massen beider Kugeln
    let l_sm1m2 = p_c1.m + p_c2.m;
    
    // Überlappung der beiden Kugeln
    let l_overlap = (p_c1.r + p_c2.r) - l_dist;
    
    // Verschieben der beiden Kugeln entlang der Normalen,
    // so dass sie sich nicht mehr überlappen!
    // Die Massen werden berücksichtigt. Schwerere Kreise werden
    // weniger weit verschoben.
    l_overlap += 2;     /* fight penetration */ 
    l_overlap *= 1.001; /* fight penetration */
    p_c1.x = p_c1.x - l_nx * l_overlap * (p_c2.m / l_sm1m2);
    p_c1.y = p_c1.y - l_ny * l_overlap * (p_c2.m / l_sm1m2);
    p_c2.x = p_c2.x + l_nx * l_overlap * (p_c1.m / l_sm1m2);
    p_c2.y = p_c2.y + l_ny * l_overlap * (p_c1.m / l_sm1m2);
    
    // Zerlegung der Geschwindigkeitsvektoren in Normalen- und
    // Tangentialanteil: v=sn*n+st*t, wobei
    // v Vektor, n Normalenvektor, t Tagentialvektor und
    // sn, st zwei skalare Werte sind.
    // Es gilt: v*n = sn*(n*n)+st*(t*n) = sn, da t*n=0 und n*n = 1
    // Es gilt: v*t = sn*(n*t)+st*(t*t) = st, da t*n=0 und t*t = 1
    // Also ist: sn = v*n und st=v*t
    
    // Ball 1: Zerlegung des Geschwindigkeitsvektors in n- und t-Anteil
    let l_sn1 = l_nx * p_c1.vx + l_ny * p_c1.vy;
    let l_st1 = l_tx * p_c1.vx + l_ty * p_c1.vy;
    
    let l_n1x = l_nx * l_sn1; // Normalenvektor-Anteil von p_c1.vx
    let l_n1y = l_ny * l_sn1; // Normalenvektor-Anteil von p_c1.vy
    
    let l_t1x = l_tx * l_st1; // Tangentialvektor-Anteil von p_c1.vx
    let l_t1y = l_ty * l_st1; // Tangentialvektor-Anteil von p_c1.vy
    
    // Ball 2: Zerlegung des Geschwindigkeitsvektors in n- und t-Anteil
    let l_sn2 = l_nx * p_c2.vx + l_ny * p_c2.vy;
    let l_st2 = l_tx * p_c2.vx + l_ty * p_c2.vy;
    
    let l_n2x = l_nx * l_sn2; // Normalenvektor-Anteil von p_c2.vx
    let l_n2y = l_ny * l_sn2; // Normalenvektor-Anteil von p_c2.vy
    
    let l_t2x = l_tx * l_st2; // Tangentialvektor-Anteil von p_c2.vx
    let l_t2y = l_ty * l_st2; // Tangentialvektor-Anteil von p_c2.vy
    
    // Der Impulserhaltungssatz
    //   m1*v1 + m2*v2 = m1*v1' + m2*v2'
    //   (wobei m1, m2 = Massen der Körper
    //    und v1, v2, v1', v2' die Geschwindigkeiten)
    // und der Energieerhaltungssatz
    //   0,5*m1*v1² + 0,5*m2*v2² = 0,5*m1*v1'² + 0,5*m2*v2'²
    // führen nach einfachen mathematischen Umformungen zu
    // folgenden Beziehungen (für den eindimensionalen Fall):
    //   v1' = 2*(m1*v1+m2*v2)/(m1+m2) - v1
    //   v2' = 2*(m1*v1+m2*v2)/(m1+m2) - v2
    //   2*(m1*v1+m2*v2)/(m1+m2) ist die Geschwindigkeit des
    //                           gemeinsamen Schwerpunktes
    //                           (center of gravity).    
    // Im zweidimensionalen Fall gilt, dass die Kollision entlang
    // der Normalen erfolgt. Die tangentialen Anteile der der
    // Bewegungsrichtungen werden unverändert übernommen.
    
    let l_vcgx = 2*(p_c1.m * l_n1x + p_c2.m * l_n2x) / l_sm1m2;
    let l_vcgy = 2*(p_c1.m * l_n1y + p_c2.m * l_n2y) / l_sm1m2;
    
    p_c1.vx = l_vcgx - l_n1x + l_t1x;
    p_c1.vy = l_vcgy - l_n1y + l_t1y;
    p_c2.vy = l_vcgx - l_n2x + l_t2x;
    p_c2.vy = l_vcgy - l_n2y + l_t2y;
    
    //// Alternative Berechnung:
    // Differenz der Massen beide Kugeln
    // let l_dm2m1 = p_c2.m - p_c1.m;
    // p_c1.vx = (l_n2x*p_c2.m*2-l_n1x*l_dm2m1)/l_sm1m2 + l_t1x;
    // p_c1.vy = (l_n2y*p_c2.m*2-l_n1y*l_dm2m1)/l_sm1m2 + l_t1y;
    // p_c2.vx = (l_n1x*p_c1.m*2+l_n2x*l_dm2m1)/l_sm1m2 + l_t2x;
    // p_c2.vy =(l_n1y*p_c1.m*2+l_n2y*l_dm2m1)/l_sm1m2 + l_t2y;
    return true;
  }
  else
  { return false; }
}

A-priori-Kollisionserkennung von zwei Kugeln

Kollision zweier Kugeln
Der Tunnel-Effekt

Quellen

  1. Kowarschick (WebProg): Wolfgang Kowarschick; Vorlesung „Web-Programmierung“; Hochschule: Hochschule Augsburg; Adresse: Augsburg; Web-Link; 2024; Quellengüte: 3 (Vorlesung)