Determine if two rectangles overlap each other?

前端 未结 23 831
礼貌的吻别
礼貌的吻别 2020-11-22 04:09

I am trying to write a C++ program that takes the following inputs from the user to construct rectangles (between 2 and 5): height, width, x-pos, y-pos. All of these rectang

相关标签:
23条回答
  • 2020-11-22 05:00

    Suppose that you have defined the positions and sizes of the rectangles like this:

    enter image description here

    My C++ implementation is like this:

    class Vector2D
    {
        public:
            Vector2D(int x, int y) : x(x), y(y) {}
            ~Vector2D(){}
            int x, y;
    };
    
    bool DoRectanglesOverlap(   const Vector2D & Pos1,
                                const Vector2D & Size1,
                                const Vector2D & Pos2,
                                const Vector2D & Size2)
    {
        if ((Pos1.x < Pos2.x + Size2.x) &&
            (Pos1.y < Pos2.y + Size2.y) &&
            (Pos2.x < Pos1.x + Size1.x) &&
            (Pos2.y < Pos1.y + Size1.y))
        {
            return true;
        }
        return false;
    }
    

    An example function call according to the given figure above:

    DoRectanglesOverlap(Vector2D(3, 7),
                        Vector2D(8, 5),
                        Vector2D(6, 4),
                        Vector2D(9, 4));
    

    The comparisons inside the if block will look like below:

    if ((Pos1.x < Pos2.x + Size2.x) &&
        (Pos1.y < Pos2.y + Size2.y) &&
        (Pos2.x < Pos1.x + Size1.x) &&
        (Pos2.y < Pos1.y + Size1.y))
                     ↓  
    if ((   3   <    6   +   9    ) &&
        (   7   <    4   +   4    ) &&
        (   6   <    3   +   8    ) &&
        (   4   <    7   +   5    ))
    
    0 讨论(0)
  • 2020-11-22 05:01

    I have a very easy solution

    let x1,y1 x2,y2 ,l1,b1,l2,be cordinates and lengths and breadths of them respectively

    consider the condition ((x2

    now the only way these rectangle will overlap is if the point diagonal to x1,y1 will lie inside the other rectangle or similarly the point diagonal to x2,y2 will lie inside the other rectangle. which is exactly the above condition implies.

    0 讨论(0)
  • 2020-11-22 05:02

    It is easier to check if a rectangle is completly outside the other, so if it is either

    on the left...

    (r1.x + r1.width < r2.x)
    

    or on the right...

    (r1.x > r2.x + r2.width)
    

    or on top...

    (r1.y + r1.height < r2.y)
    

    or on the bottom...

    (r1.y > r2.y + r2.height)
    

    of the second rectangle, it cannot possibly collide with it. So to have a function that returns a Boolean saying weather the rectangles collide, we simply combine the conditions by logical ORs and negate the result:

    function checkOverlap(r1, r2) : Boolean
    { 
        return !(r1.x + r1.width < r2.x || r1.y + r1.height < r2.y || r1.x > r2.x + r2.width || r1.y > r2.y + r2.height);
    }
    

    To already receive a positive result when touching only, we can change the "<" and ">" by "<=" and ">=".

    0 讨论(0)
  • 2020-11-22 05:03

    This is a very fast way to check with C++ if two rectangles overlap:

    return std::max(rectA.left, rectB.left) < std::min(rectA.right, rectB.right)
        && std::max(rectA.top, rectB.top) < std::min(rectA.bottom, rectB.bottom);
    

    It works by calculating the left and right borders of the intersecting rectangle, and then comparing them: if the right border is equal to or less than the left border, it means that the intersection is empty and therefore the rectangles do not overlap; otherwise, it tries again with the top and bottom borders.

    What is the advantage of this method over the conventional alternative of 4 comparisons? It's about how modern processors are designed. They have something called branch prediction, which works well when the result of a comparison is always the same, but have a huge performance penalty otherwise. However, in the absence of branch instructions, the CPU performs quite well. By calculating the borders of the intersection instead of having two separate checks for each axis, we're saving two branches, one per pair.

    It is possible that the four comparisons method outperforms this one, if the first comparison has a high chance of being false. That is very rare, though, because it means that the second rectangle is most often on the left side of the first rectangle, and not on the right side or overlapping it; and most often, you need to check rectangles on both sides of the first one, which normally voids the advantages of branch prediction.

    This method can be improved even more, depending on the expected distribution of rectangles:

    • If you expect the checked rectangles to be predominantly to the left or right of each other, then the method above works best. This is probably the case, for example, when you're using the rectangle intersection to check collisions for a game, where the game objects are predominantly distributed horizontally (e.g. a SuperMarioBros-like game).
    • If you expect the checked rectangles to be predominantly to the top or bottom of each other, e.g. in an Icy Tower type of game, then checking top/bottom first and left/right last will probably be faster:
    return std::max(rectA.top, rectB.top) < std::min(rectA.bottom, rectB.bottom)
        && std::max(rectA.left, rectB.left) < std::min(rectA.right, rectB.right);
    
    • If the probability of intersecting is close to the probability of not intersecting, however, it's better to have a completely branchless alternative:
    return std::max(rectA.left, rectB.left) < std::min(rectA.right, rectB.right)
         & std::max(rectA.top, rectB.top) < std::min(rectA.bottom, rectB.bottom);
    

    (Note the change of && to a single &)

    0 讨论(0)
  • 2020-11-22 05:03

    For those of you who are using center points and half sizes for their rectangle data, instead of the typical x,y,w,h, or x0,y0,x1,x1, here's how you can do it:

    #include <cmath> // for fabsf(float)
    
    struct Rectangle
    {
        float centerX, centerY, halfWidth, halfHeight;
    };
    
    bool isRectangleOverlapping(const Rectangle &a, const Rectangle &b)
    {
        return (fabsf(a.centerX - b.centerX) <= (a.halfWidth + b.halfWidth)) &&
               (fabsf(a.centerY - b.centerY) <= (a.halfHeight + b.halfHeight)); 
    }
    
    0 讨论(0)
  • 2020-11-22 05:04
    struct rect
    {
        int x;
        int y;
        int width;
        int height;
    };
    
    bool valueInRange(int value, int min, int max)
    { return (value >= min) && (value <= max); }
    
    bool rectOverlap(rect A, rect B)
    {
        bool xOverlap = valueInRange(A.x, B.x, B.x + B.width) ||
                        valueInRange(B.x, A.x, A.x + A.width);
    
        bool yOverlap = valueInRange(A.y, B.y, B.y + B.height) ||
                        valueInRange(B.y, A.y, A.y + A.height);
    
        return xOverlap && yOverlap;
    }
    0 讨论(0)
提交回复
热议问题