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
Zeile 7: Zeile 7:
}}
}}
{{In Bearbeitung}}
{{In Bearbeitung}}
[[Datei:KollisionZweiKugeln1.png|miniatur|375px|Kollision zweier Kugeln]]
[[Datei:KollisionZweiKugeln2.png|miniatur|461px|Der Tunnel-Effekt]]


==Grundannahmen==
==Grundannahmen==
Zeile 30: Zeile 28:
</source>
</source>


Anschließend wird der Beschleunigungsvektor analog angepasst:
Anschließend wird der Beschleunigungsvektor analog angepasst:


<source lang="javascript">
<source lang="javascript">
Zeile 45: Zeile 43:
   {
   {
     // l_n: Normalenvektor (Verbindung zwischen den beiden Kugelnn)
     // l_n: Normalenvektor (Verbindung zwischen den beiden Kugelnn)
     var l_nx = p_b2.getX() - p_b1.getX();
     var l_nx = p_b2.x() - p_b1.x();
     var l_ny = p_b2.getY() - p_b1.getY();
     var l_ny = p_b2.y() - p_b1.y();
    
    
     // Abstand der beiden Kugeln
     // Abstand der beiden Kugeln
Zeile 58: Zeile 56:
     if (l_dist < EPSILON)
     if (l_dist < EPSILON)
     {
     {
       p_b2.setX(p_b2.getX()+ p_b2.getR());
       p_b2.x = p_b2.x+ p_b2.r;
       l_nx += p_b2.getR();
       l_nx += p_b2.r;
       l_dist = Math.sqrt( l_nx * l_nx + l_ny * l_ny );
       l_dist = Math.sqrt( l_nx * l_nx + l_ny * l_ny );
     };
     };
Zeile 76: Zeile 74:
          
          
       // Summe der Massen beider Kugeln
       // Summe der Massen beider Kugeln
       var l_sm1m2 = p_b1.getMass() + p_b2.getMass();
       var l_sm1m2 = p_b1.m + p_b2.m;
    
    
       // Überlappung der beiden Kugeln
       // Überlappung der beiden Kugeln
       var l_overlap = ( p_b1.getR() + p_b2.getR() ) - l_dist;
       var l_overlap = ( p_b1.r+ p_b2.r ) - l_dist;
    
    
       // Verschieben der beiden Kugeln entlang der Normalen,
       // Verschieben der beiden Kugeln entlang der Normalen,
       // so dass sie sich nicht mehr überlappen!
       // 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.x = p_b1.x - l_nx * l_overlap * (p_b2.m/l_sm1m2) * (1+EPSILON));
       p_b1.setY(p_b1.getY() - l_ny * l_overlap * (p_b2.getMass()/l_sm1m2) * (1+EPSILON));
       p_b1.y = p_b1.y - l_ny * l_overlap * (p_b2.m/l_sm1m2) * (1+EPSILON));
       p_b2.setX(p_b2.getX() + l_nx * l_overlap * (p_b1.getMass()/l_sm1m2) * (1+EPSILON));
       p_b2.x = p_b2.x + l_nx * l_overlap * (p_b1.m/l_sm1m2) * (1+EPSILON));
       p_b2.setY(p_b2.getY() + l_ny * l_overlap * (p_b1.getMass()/l_sm1m2) * (1+EPSILON));
       p_b2.y = p_b2.y + l_ny * l_overlap * (p_b1.m/l_sm1m2) * (1+EPSILON));
    
    
       // Zerlegung der Geschwindigkeitsvektoren in Normalen- und  
       // Zerlegung der Geschwindigkeitsvektoren in Normalen- und  
Zeile 97: Zeile 95:


       // Ball 1: Zerlegung des Geschwindigkeitsvektors in n- und t-Anteil
       // 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_sn1 = l_nx * p_b1.vx + l_ny * p_b1.vy;
       var l_st1 = l_tx * p_b1.getVx() + l_ty * p_b1.getVy();
       var l_st1 = l_tx * p_b1.vx + l_ty * p_b1.vy;


       var l_n1x = l_nx * l_sn1; // Normalenvektor-Anteil von p_b1.getVx()
       var l_n1x = l_nx * l_sn1; // Normalenvektor-Anteil von p_b1.vx
       var l_n1y = l_ny * l_sn1;
       var l_n1y = l_ny * l_sn1;
        
        
       var l_t1x = l_tx * l_st1; // Tangentialvektor-Anteil von p_b1.getVx()
       var l_t1x = l_tx * l_st1; // Tangentialvektor-Anteil von p_b1.vx
       var l_t1y = l_ty * l_st1;
       var l_t1y = l_ty * l_st1;
          
          
Zeile 110: Zeile 108:
       var l_st2 = l_tx * p_b2.getVx() + l_ty * 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_n2x = l_nx * l_sn2; // Normalenvektor-Anteil von p_b2.vx
       var l_n2y = l_ny * l_sn2;
       var l_n2y = l_ny * l_sn2;
            
            
       var l_t2x = l_tx * l_st2; // Tangentialvektor-Anteil von p_b2.getVx()
       var l_t2x = l_tx * l_st2; // Tangentialvektor-Anteil von p_b2.vx
       var l_t2y = l_ty * l_st2;
       var l_t2y = l_ty * l_st2;
              
              
Zeile 132: Zeile 130:
       // Bewegungsrichtungen werden unverändert übernommen.
       // Bewegungsrichtungen werden unverändert übernommen.
          
          
       var l_vspx = 2*(p_b1.getMass()*l_n1x+p_b2.getMass()*l_n2x)/l_sm1m2;
       var l_vspx = 2*(p_b1.m*l_n1x+p_b2.m*l_n2x)/l_sm1m2;
       var l_vspy = 2*(p_b1.getMass()*l_n1y+p_b2.getMass()*l_n2y)/l_sm1m2;
       var l_vspy = 2*(p_b1.m*l_n1y+p_b2.m*l_n2y)/l_sm1m2;
          
          
       p_b1.setVx(l_vspx - l_n1x + l_t1x);
       p_b1.vx = l_vspx - l_n1x + l_t1x;
       p_b1.setVy(l_vspy - l_n1y + l_t1y);
       p_b1.vy = l_vspy - l_n1y + l_t1y;
       p_b2.setVx(l_vspx - l_n2x + l_t2x);
       p_b2.vy = l_vspx - l_n2x + l_t2x;
       p_b2.setVy(l_vspy - l_n2y + l_t2y);
       p_b2.vy = l_vspy - l_n2y + l_t2y;
          
          
       //// Alternative Berechnung:
       //// Alternative Berechnung:
       // Differenz der Massen beide Kugeln
       // Differenz der Massen beide Kugeln
       // var l_dm2m1 = p_b2.getMass() - p_b1.getMass();
       // var l_dm2m1 = p_b2.m - p_b1.m;
       // p_b1.setVx((l_n2x*p_b2.getMass()*2-l_n1x*l_dm2m1)/l_sm1m2 + l_t1x);
       // p_b1.vx = (l_n2x*p_b2.m*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_b1.vy = (l_n2y*p_b2.m*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.vx = (l_n1x*p_b1.m*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);
       // p_b2.vy =(l_n1y*p_b1.m*2+l_n2y*l_dm2m1)/l_sm1m2 + l_t2y;
   }
   }
}
}
Zeile 152: Zeile 150:


==[[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/>

Version vom 1. November 2016, 10:26 Uhr

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.

Grundannahmen

Ein Ball-Objekt b habe folgende Attribute:

  • x, y: Position (Einheit: Pixel)
  • vx, vy: Geschwindigkeit in $x$- und $y$-Richtung (Einheit: Pixel/s)
  • ax, ay: Beschleunigung 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 Berechnung der Position aller im System vorhandener Bälle erfolgt fps (frames per second) mal pro Sekunde. Wenn es zu keiner Kollision kommt, wird der Ball um vx/fps bzw. vy/fps Pixel in $x$- bzw. $y$-Richtung verschoben:

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

Anschließend wird der Beschleunigungsvektor analog angepasst:

  b.vx += b.ax/fps;
  b.vy += b.ay/fps;

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

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.x() - p_b1.x();
    var l_ny = p_b2.y() - p_b1.y();
  
    // 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.x = p_b2.x+ p_b2.r;
      l_nx += p_b2.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_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.m + p_b2.m;
   
      // Überlappung der beiden Kugeln
      var l_overlap = ( p_b1.r+ p_b2.r ) - l_dist;
   
      // Verschieben der beiden Kugeln entlang der Normalen,
      // so dass sie sich nicht mehr überlappen!
      p_b1.x = p_b1.x - l_nx * l_overlap * (p_b2.m/l_sm1m2) * (1+EPSILON));
      p_b1.y = p_b1.y - l_ny * l_overlap * (p_b2.m/l_sm1m2) * (1+EPSILON));
      p_b2.x = p_b2.x + l_nx * l_overlap * (p_b1.m/l_sm1m2) * (1+EPSILON));
      p_b2.y = p_b2.y + l_ny * l_overlap * (p_b1.m/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.vx + l_ny * p_b1.vy;
      var l_st1 = l_tx * p_b1.vx + l_ty * p_b1.vy;

      var l_n1x = l_nx * l_sn1; // Normalenvektor-Anteil von p_b1.vx
      var l_n1y = l_ny * l_sn1;
       
      var l_t1x = l_tx * l_st1; // Tangentialvektor-Anteil von p_b1.vx
      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.vx
      var l_n2y = l_ny * l_sn2;
          
      var l_t2x = l_tx * l_st2; // Tangentialvektor-Anteil von p_b2.vx
      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.m*l_n1x+p_b2.m*l_n2x)/l_sm1m2;
      var l_vspy = 2*(p_b1.m*l_n1y+p_b2.m*l_n2y)/l_sm1m2;
        
      p_b1.vx = l_vspx - l_n1x + l_t1x;
      p_b1.vy = l_vspy - l_n1y + l_t1y;
      p_b2.vy = l_vspx - l_n2x + l_t2x;
      p_b2.vy = l_vspy - l_n2y + l_t2y;
        
      //// Alternative Berechnung:
      // Differenz der Massen beide Kugeln
      // var l_dm2m1 = p_b2.m - p_b1.m;
      // p_b1.vx = (l_n2x*p_b2.m*2-l_n1x*l_dm2m1)/l_sm1m2 + l_t1x;
      // p_b1.vy = (l_n2y*p_b2.m*2-l_n1y*l_dm2m1)/l_sm1m2 + l_t1y;
      // p_b2.vx = (l_n1x*p_b1.m*2+l_n2x*l_dm2m1)/l_sm1m2 + l_t2x;
      // p_b2.vy =(l_n1y*p_b1.m*2+l_n2y*l_dm2m1)/l_sm1m2 + l_t2y;
  }
}

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)