2012-11-01 2 views
4

J'essaie d'écrire ma propre implémentation du théorème de l'axe de séparation, mais j'ai du mal à le faire fonctionner aussi précisément que je le veux. Je ne peux pas le dire avec certitude, mais on dirait qu'il y a une collision quand une boîte imaginaire autour des formes se heurte comme dans la première forme. Mais la deuxième forme fonctionne parfaitement.Implémentation de détection de collision de polygone

est ici les données de sommet pour le carré (coordonnées exactes):

vertsx = [ 200, 220, 220, 200 ] 
vertsy = [ 220, 220, 200, 200 ] 

Voici les données de sommet pour la forme de test 1 (par rapport à la souris):

vertsx = [ -10, 0, 10, 10, -10 ] 
vertsy = [ -10, -50, -10, 10, 10 ] 

Enfin voici les données de sommet pour la forme de test 2 (par rapport à la souris):

vertsx = [ -10, 0, 10, 10, -10 ] 
vertsy = [ -10, -20, -10, 10, 10 ] 

Juste pour clarifier le roumain traduit rdinates sont ceux qui sont testés et ceux-ci ont des formes ont été testés avec les coordonnées ordonnées comme indiqué.

enter image description here

est ici la fonction réelle.

function collisionConvexPolygon (vertsax, vertsay, vertsbx, vertsby) { 
    var alen = vertsax.length; 
    var blen = vertsbx.length; 
    // Loop for axes in Shape A 
    for (var i = 0, j = alen - 1; i < alen; j = i++) { 
     // Get the axis 
     var vx = vertsax[ j ] - vertsax[ i ]; 
     var vy = -(vertsay[ j ] - vertsay[ i ]); 
     var len = Math.sqrt(vx * vx + vy * vy); 

     vx /= len; 
     vy /= len; 

     // Project shape A 
     var max0 = vertsax[ 0 ] * vx + vertsay[ 0 ] * vy, min0 = max0; 
     for (k = 1; k < alen; k++) { 
      var proja = vertsax[ k ] * vx + vertsay[ k ] * vy; 

      if (proja > max0) { 
       max0 = proja; 
      } 
      else if (proja < min0) { 
       min0 = proja; 
      } 
     } 
     // Project shape B 
     var max1 = vertsbx[ 0 ] * vx + vertsby[ 0 ] * vy, min1 = max1; 
     for (var k = 1; k < blen; k++) { 
      var projb = vertsbx[ k ] * vx + vertsby[ k ] * vy; 

      if (projb > max1) { 
       max1 = projb; 
      } 
      else if (projb < min1) { 
       min1 = projb; 
      } 
     } 
     // Test for gaps 
     if (!axisOverlap(min0, max0, min1, max1)) { 
      return false; 
     } 
    } 
    // Loop for axes in Shape B (same as above) 
    for (var i = 0, j = blen - 1; i < blen; j = i++) { 
     var vx = vertsbx[ j ] - vertsbx[ i ]; 
     var vy = -(vertsby[ j ] - vertsby[ i ]); 
     var len = Math.sqrt(vx * vx + vy * vy); 

     vx /= len; 
     vy /= len; 

     var max0 = vertsax[ 0 ] * vx + vertsay[ 0 ] * vy, min0 = max0; 
     for (k = 1; k < alen; k++) { 
      var proja = vertsax[ k ] * vx + vertsay[ k ] * vy; 

      if (proja > max0) { 
       max0 = proja; 
      } 
      else if (proja < min0) { 
       min0 = proja; 
      } 
     } 
     var max1 = vertsbx[ 0 ] * vx + vertsby[ 0 ] * vy, min1 = max1; 
     for (var k = 1; k < blen; k++) { 
      var projb = vertsbx[ k ] * vx + vertsby[ k ] * vy; 

      if (projb > max1) { 
       max1 = projb; 
      } 
      else if (projb < min1) { 
       min1 = projb; 
      } 
     } 
     if (!axisOverlap(min0, max0, min1, max1)) { 
      return false; 
     } 
    } 
    return true; 
} 

Je vais essayer d'autres formes si vous avez besoin de moi.

Voici ma fonction axisOverlap.

function axisOverlap (a0, a1, b0, b1) { 
    return !(a0 > b1 || b0 > a1); 
} 
+0

Pouvez-vous publier votre 'axisOverlap()' fonction aussi? – techfoobar

+0

Pourriez-vous s'il vous plaît essayer ceci sans inverser la direction de vy? –

+0

@Asad Oui, malheureusement, il n'a pas changé le résultat. – SpaceFace

Répondre

6

Je l'ai compris!

J'ai commencé à tracer des lignes numériques sur papier et j'ai réalisé que le problème était que mes axes n'étaient pas calculés correctement. Pour calculer un vecteur perpendiculaire, vous devez échanger les coordonnées x et y et ensuite inverser un, j'ai complètement oublié d'échanger les coordonnées.

Le nouveau code

var vx = vertsay[ i ] - vertsay[ j ]; 
var vy = -(vertsax[ i ] - vertsax[ j ]); 
+0

Si vous avez résolu votre question, alors marquez votre réponse comme _the_ réponse! –

+3

@ A.Webb ne peut pas pour 2 jours. – SpaceFace