Polygon collision detection implementation

I am trying to write my own implementation of the dividing axis theorem, but I have some problems in order for it to work as exactly as I want. I can’t say for sure, but it seems that this speaks of a collision when an imaginary box around the figures collides, as in the first form. But the second form works great.

Here are the vertex data for the square (exact coordinates):

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

Here is the vertex data for test form 1 (relative to the mouse):

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

And finally, the vertex data for test form 2 (relative to the mouse):

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

For illustrative purposes only, the translated coordinates are verified, and they have forms that have been verified with the coordinates ordered as shown.

enter image description here

Here is the actual function.

 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; } 

I will try other forms if you need.

Here is my axisOverlap function.

 function axisOverlap ( a0, a1, b0, b1 ) { return !( a0 > b1 || b0 > a1 ); } 
+4
source share
1 answer

I get it!

I began to draw numerical lines on paper and realized that the problem was that my axes were not calculated correctly. To calculate the perpendicular vector, you need to change the x and y coordinates and THEN invert one, I completely forgot to change the coordinates.

New code

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

Source: https://habr.com/ru/post/1443374/


All Articles