Kollision zweier Kugeln (2D)

aus GlossarWiki, der Glossar-Datenbank der Fachhochschule Augsburg

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

Korrektheit: 0
(nicht überprüft)
Umfang: 0
(viel zu gering)
Quellenangaben: 1
(fehlen großteils)
Quellenarten: 3
(gut)
Konformität: 5
(ausgezeichnet)

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

Kollision zweier Kugeln
Der Tunnel-Effekt

Grundannahmen

A-posteriori-Kollisionserkennung von zwei Kugeln

  function collisionBallBall(p_b1, p_b2)
  {
    // l_n: Normalenvektor (Verbindung zwischen den beiden Kugelnn)
    var l_nx = p_b2.getX() - p_b1.getX();
    var l_ny = p_b2.getY() - p_b1.getY();
  
    // Abstand der beiden Kugeln
    var 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_b2.setX(p_b2.getX()+ p_b2.getR());
      l_nx += p_b2.getR();
      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_b1.getR() + p_b2.getR())
    {
      // Normalenvektor wird normalisiert: |l_n| = 1
      l_nx /= l_dist;
      l_ny /= l_dist;
        
      //Tangentialvektor (senkrecht zu Normalenvektor, zwischen beiden Kugeln)
      var l_tx = l_ny;
      var l_ty = -l_nx;
        
      // Summe der Massen beider Kugeln
      var l_sm1m2 = p_b1.getMass() + p_b2.getMass();
   
      // Überlappung der beiden Kugeln
      var l_overlap = ( p_b1.getR() + p_b2.getR() ) - l_dist;
   
      // Verschieben der beiden Kugeln entlang der Normalen,
      // so dass sie sich nicht mehr überlappen!
      p_b1.setX(p_b1.getX() - l_nx * l_overlap * (p_b2.getMass()/l_sm1m2) * (1+EPSILON));
      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));
      p_b2.setY(p_b2.getY() + l_ny * l_overlap * (p_b1.getMass()/l_sm1m2) * (1+EPSILON));
  
      // 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
      var l_sn1 = l_nx * p_b1.getVx() + l_ny * p_b1.getVy();
      var l_st1 = l_tx * p_b1.getVx() + l_ty * p_b1.getVy();

      var l_n1x = l_nx * l_sn1; // Normalenvektor-Anteil von p_b1.getVx()
      var l_n1y = l_ny * l_sn1;
       
      var l_t1x = l_tx * l_st1; // Tangentialvektor-Anteil von p_b1.getVx()
      var l_t1y = l_ty * l_st1;
        
      // Ball 2: Zerlegung des Geschwindigkeitsvektors in n- und t-Anteil
      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();
            
      var l_n2x = l_nx * l_sn2; // Normalenvektor-Anteil von p_b2.getVx()
      var l_n2y = l_ny * l_sn2;
          
      var l_t2x = l_tx * l_st2; // Tangentialvektor-Anteil von p_b2.getVx()
      var l_t2y = l_ty * l_st2;
             
      // Der Impulserhaltungssatz
      //   m1*v1 + m2*v2 = m1*u1 + m2*u2 
      //   (wobei m1, m2 = Massen der Körper 
      //    und v1, v2, u1, u2 die Geschwindigkeiten)
      // und der Energieerhaltsungssatz
      //   0,5*m1*v1² + 0,5*m2*v2² = 0,5*m1*u1² + 0,5*m2*u2²
      // führen nach einfachen mathematischen Umformungen zu
      // folgenden Beziehungen (für den eindimensionalen Fall):
      //   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);
  }
}

A-priori-Kollisionserkennung von zwei Kugeln

Quellen

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