“检查”如果两个不同的几何形状对象发生碰撞

时间:2013-04-14 02:07:29

标签: c++ c geometry

我只是想“检查”如果两个不同的几何形状对象发生碰撞。一个是圆形,第二个是正方形。我搜索谷歌找到一个简单的例子并从中学习,因为我不知道该怎么做。我找到了这个例子,尝试过,但没有发生任何事情。代码中存在大多数错误。请帮我用C或C ++语言纠正它。

bool Collision(int circleX, int circleY, int radius, int squareX, int squareY, int width, int height)
{
    int distance = 0;

    if(circleX < squareX) 
        distance += pow(circleX - boxX,2); //x-axis
    else if (circleX > squareX + width)
        distance += pow(circleX - squareX - width, 2);

    if(circleY < squareY) 
        distance += pow(circleY - squareY,2); //y-axis
    else if (circleY > squareY + height) 
        distance += pow(circleY - squareY - height, 2);

    if( distance <= pow(radius, 2))
        return true; 
    else    
        return false;
}

2 个答案:

答案 0 :(得分:3)

首先,让我们清楚如何表示一个圆圈和一个正方形。

按惯例,square表示如下:

  squarexX, squareY + height  ------------ squareX+ width, squareY +height
  |                                               |
  |                                               |
   squareX, squareY          ------------- squareX + width, squareY

circle由圆圈(circleX, circleY)radius的坐标表示。考虑到这一点,您甚至可以编写自己的功能。请注意,圆圈没有宽度或高度。

所以在他们的代码中:

 if(circleX < squareX) distance += pow(circleX - boxX,2); //x-axis

应该是

 if(circleX < squareX) distance += pow(circleX - squareX,2); //x-axis

决定方块是否与圆重叠/碰撞的想法如下:

  1. 假设square位于2D平面的原点,如果不是,我们可以将原点移动到正方形中心
  2. 接下来,找出圆与最近边交点之间的距离 如果该距离大于半径,则没有重叠, 否则,重叠。一个特殊情况是,如果圆位于正方形内,那么所谓的交点就是圆本身的中心。在这种情况下,testForCollision将返回true。
  3. 完整功能应如下所示:

    //this function computes the distance between center of circle
    //to closest point on one of the edges of square, that edge is on the
    //same side as the circle
    #include <algorithm>
    bool testForCollision(int circleX, int circleY, int width, int height, int radius)
    {   
    
        int dx = std::min(circleX, (int)(width  * 0.5));
        int dx1 = std::max(dx, (int)(-width *0.5));
    
        int dy = std::min(circleY, (int)(height * 0.5));
        int dy1 = std::max(dy, (int)(-height * 0.5));
    
        return (dx1 - circleX) * (dx1 - circleX) 
               + (dy1 - circleY) * (dy1 - circleY) <= radius * radius;
    }
    
    
    bool Collision(int circleX, int circleY, int radius, 
                   int squareX, int squareY, int width, int height)
    {
    
        //get center of square
        int center_of_square_x = squareX + width/2;
        int center_of_square_y = squareY + height/2;
    
        //if square is already at origin, test directly
        if ( center_of_square_x == 0 && center_of_square_y ==0)
        {
            return testForCollision(circleX, circleY, width, height, radius);
        }
        else
        {
            //shift center of square to origin and update coordinates of circle
            //only consider part of the situation, more to add about shifting
            circleX = circleX - center_of_square_x;
            circleY = circleY - center_of_square_y;
            return testForCollision(circleX, circleY, width, height, radius);
        }
    }
    

    这样,它应该能够识别圆形和方形是否相互碰撞。

    编辑:让我们来看一个测试用例:

    circleX = 60 circleY = 172 radius = 39
    squareX = 120 squareY = 180 width = 72 height = 72 
    

    我们有正方形的坐标如下(包括中心)

    120, 252  -------- 192, 252
     |                   |
     |--------156,216----|
     |                   |
    120,180   ---------192,180
    

    我们可以看到(60,172)左边缘(120,252) - >(120,180),(120,180)和(60,72)之间的距离大于39.(120,252)和(120)之间的距离60,72)也大于39,没有重叠。为了更好地理解它,给定圆心(60,172)和半径39,你可以从圆心到达的x和y的范围是(60-39,60 +39)=(21,99)和( 172-39,172 + 39)=(133,211)。如果你想象它,它应该与正方形不重叠。

    如果你首先将原点变换为(156,216),我们在新坐标系中得到(-96,-44)圆的中心。它位于第三象限。如果你运行testForCollision函数,你会发现没有重叠。

    dx = min(-96,36) = -96
    dx1 = max(dx, -36) = -36
    dy = min(-44, 36) = -44
    dy1 = max(dy,-36) = -36
    
    distance = (-36 - (-96))^2 + (-36 - (-44))^2 = 60^2 + 8^2 > 39^2, so no overlap
    

答案 1 :(得分:2)

有3例:

  • 形状重叠,因此一个形状的边缘与另一个形状的边缘交叉
  • 完全在广场内的圆圈(例如想象一个巨大的矩形,其中有一个小圆圈)
  • 完全在圆圈内的矩形(例如,想象一个带有一个小矩形的巨大圆圈)

首先确定圆心和矩形中心之间的距离。我们称之为距离D.

然后找到足够小以适合矩形内部的最大圆圈。它的直径等于矩形的高度或矩形的宽度(以较小者为准)。如果新圆的半径加上原始圆的半径小于距离D那么肯定会发生碰撞。

然后找到足够大的最小圆圈以包含整个矩形。这个圆的半径可以用毕达哥拉斯(从矩形中心到矩形的任何角落的距离)找到。如果这个新圆的半径加上原始圆的半径大于距离D那么就不会有任何碰撞。

如果这两个测试都没有给你答案;然后,两个形状都不完全在另一个内部,但它们可能重叠或不重叠;因此,您必须确定一个形状的边缘是否与另一个形状的边缘相交。要做到这一点,扩展所有矩形的边缘,使它们是无限长度(使用线段来描述一条线);并尝试通过将x或y“插入”圆形公式来计算这些无限长度线与圆周相交的位置(注意:您将找到没有交点,1个交点或2个交点)。如果有2个交叉点,则必须测试其中一个是否为边缘。

例如,如果矩形的上边缘位于y = 2,则将y = 2插入您的formala中以获得圆圈。如果你发现这条线在x = 3和x = 6`处相交,那么测试3和6是否在矩形的左边缘和矩形的右边缘之间 - 如果它们是那么边缘圆圈与矩形的上边缘相交,然后发生碰撞。

如果对矩形的所有4个边进行“边缘交点”测试而未检测到碰撞,则无法检测到碰撞。