2

我正在尝试通过遵循此http://www.migapro.com/circle-and-rotated-rectangle-collision-detection/来实现旋转矩形和圆形之间的碰撞检测

我在 jsfiddle 中添加了代码http://jsfiddle.net/Z6KSX/2/

我在这里想念什么?

function check_coll ( circle_x,circle_y, rect_x, rect_y, rect_width, rect_height, rect_angle) 
   {

    // Rotate circle's center point back
    var rect_centerX = rect_x /2 ;
    var rect_centerY = rect_y /2 ;

    var cx = (Math.cos(rect_angle) * (circle_x - rect_centerX)) - (Math.sin(rect_angle) * (circle_y - rect_centerY)) + rect_centerX;
    var cy = (Math.sin(rect_angle) * (circle_x - rect_centerX)) + (Math.cos(rect_angle) * (circle_y - rect_centerY)) + rect_centerY;

    // Closest point
    var x, y;

    // Find the unrotated closest x point from center of unrotated circle
    if (cx < rect_x) {
        x = rect_x;
    }
    else if (cx > rect_x + rect_width){
        x = rect_x + rect_width;
    }
    else{
        x = cx;
     }

    // Find the unrotated closest y point from center of unrotated circle
    if (cy < rect_y){
        y = rect_y;
    }
    else if (cy > rect_y + rect_height) {
        y = rect_y + rect_height;
    }
    else {
        y = cy;
     }
    // Determine collision
    var collision = false;

    var c_radius = 5;
    var distance = findDistance(cx, cy, x, y);

    if (distance < c_radius) {
        collision = true; // Collision
    }
    else {
        collision = false;
    }
     return collision;
}


function findDistance (x1, y1, x2, y2) {
       var a = Math.abs(x1 - x2);
       var b = Math.abs(y1 - y2);

       var c = Math.sqrt((a * a) + (b * b));
       return c;
}

4

3 回答 3

2

呵呵,我觉得这很有趣,因为我最近花了很多时间走错路后自己解决了这个问题。

最后我想出了一个办法:

1.)只需将圆心的点旋转矩形旋转的负数。现在该点与矩形“对齐”(在矩形相对坐标空间中)。

2.) 求解圆形与 AABB。我解决它的方式在最接近圆心的矩形上给了我一个点。

3.) 将结果点从矩形旋转的正数旋转。像往常一样继续求解(检查该点与圆心之间的距离是否在圆的半径内)

快速浏览一下您的代码,似乎您正在做同样的事情,但错过了最后一步?我建议在第 2 步中的矩形上画出你的点,以准确查看它在哪里有助于调试。

于 2012-11-27T09:19:30.423 回答
0

我能够弄清楚这一点。代码中的问题是,我使用了错误的半径并且错过了 rect_x 和 rect_y 的中心

   var rect_centerX = rect_x + (rect_width / 2);
   var rect_centerY = rect_y + (rect_height /2);

在处理画布上的旋转时,我们需要将平移值添加到 createrect 中使用的相应 x 和 y 值。

于 2012-11-29T06:30:36.770 回答
0

我也将此代码用于我的项目并且它正在工作。您唯一需要做的就是使用-angle而不是angle

这是我的代码链接

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const rectX = 100;
const rectY = 100;
const rectWidth = 200;
const rectHeight = 100;
const circleRadius = 2;
const rectMidPointX = rectX + rectWidth / 2;
const rectMidPointY = rectY + rectHeight / 2;
const angle = Math.PI / 4;
let circleX;
let circleY;


canvas.addEventListener('mousemove', (e) => {
  circleX = e.clientX;
  circleY = e.clientY;

  ctx.save();
  ctx.beginPath();
  ctx.fillStyle = '#fff';
  ctx.arc(circleX, circleY, circleRadius, 0, 2 * Math.PI);
  ctx.fill();
  ctx.stroke();
  ctx.restore();
    calculateIntersection();
})

ctx.save();

//ctx.fillRect(100, 100, 100, 100);
ctx.strokeStyle = 'black';
ctx.translate(rectMidPointX, rectMidPointY);
ctx.rotate(angle);
ctx.translate(-rectMidPointX, -rectMidPointY);
ctx.strokeRect(rectX, rectY, rectWidth, rectHeight);
ctx.restore();

// Determine collision
let collision = false;

const findDistance = (fromX, fromY, toX, toY) => {
  const a = Math.abs(fromX - toX);
  const b = Math.abs(fromY - toY);

  return Math.sqrt((a * a) + (b * b));
};


function calculateIntersection() {
  // Rotate circle's center point back
  const unrotatedCircleX = Math.cos(-angle) * (circleX - rectMidPointX) -
    Math.sin(-angle) * (circleY - rectMidPointY) + rectMidPointX;
  const unrotatedCircleY = Math.sin(-angle) * (circleX - rectMidPointX) +
    Math.cos(-angle) * (circleY - rectMidPointY) + rectMidPointY;

  // Closest point in the rectangle to the center of circle rotated backwards(unrotated)
  let closestX, closestY;

  // Find the unrotated closest x point from center of unrotated circle
  if (unrotatedCircleX < rectX)
    closestX = rectX;
  else if (unrotatedCircleX > rectX + rectWidth)
    closestX = rectX + rectWidth;
  else
    closestX = unrotatedCircleX;

  // Find the unrotated closest y point from center of unrotated circle
  if (unrotatedCircleY < rectY)
    closestY = rectY;
  else if (unrotatedCircleY > rectY + rectHeight)
    closestY = rectY + rectHeight;
  else
    closestY = unrotatedCircleY;

  const distance = findDistance(unrotatedCircleX, unrotatedCircleY, closestX, closestY);
  if (distance < circleRadius)
    collision = true; // Collision
  else
    collision = false;

  console.log('collision', collision);
}
<canvas id="canvas" width="400px" height="400px" />

于 2022-01-15T16:33:53.860 回答