我试图写一个c++程序,从用户获取以下输入来构造矩形(2和5之间):高度,宽度,x-pos, y-pos。所有这些矩形都平行于x轴和y轴,也就是说它们所有边的斜率都是0或无穷大。

我试图实现这个问题中提到的东西,但我没有太多的运气。

我目前的实现如下:

// Gets all the vertices for Rectangle 1 and stores them in an array -> arrRect1
// point 1 x: arrRect1[0], point 1 y: arrRect1[1] and so on...
// Gets all the vertices for Rectangle 2 and stores them in an array -> arrRect2

// rotated edge of point a, rect 1
int rot_x, rot_y;
rot_x = -arrRect1[3];
rot_y = arrRect1[2];
// point on rotated edge
int pnt_x, pnt_y;
pnt_x = arrRect1[2]; 
pnt_y = arrRect1[3];
// test point, a from rect 2
int tst_x, tst_y;
tst_x = arrRect2[0];
tst_y = arrRect2[1];

int value;
value = (rot_x * (tst_x - pnt_x)) + (rot_y * (tst_y - pnt_y));
cout << "Value: " << value;  

然而,我不太确定(a)我是否已经正确地实现了我链接的算法,或者如果我确实如何解释这一点?

有什么建议吗?


当前回答

if (RectA.Left < RectB.Right && RectA.Right > RectB.Left &&
     RectA.Top > RectB.Bottom && RectA.Bottom < RectB.Top ) 

或者用笛卡尔坐标

(X1是左坐标,X2是右坐标,从左到右递增,Y1是上坐标,Y2是下坐标,从下到上递增——如果这不是你的坐标系统(例如,大多数计算机的Y方向是相反的),交换下面的比较)……

if (RectA.X1 < RectB.X2 && RectA.X2 > RectB.X1 &&
    RectA.Y1 > RectB.Y2 && RectA.Y2 < RectB.Y1) 

假设你有矩形A和矩形B。 反证法是证明。四个条件中的任何一个都保证不存在重叠:

Cond1。如果A的左边在B的右边的右边, -那么A完全在B的右边 Cond2。如果A的右边在B的左边的左边, -那么A完全在B的左边 Cond3。如果A的上边在B的下边之下, -那么A完全低于B Cond4。如果A的下边在B的上边上面, -那么A完全高于B

不重叠的条件是

NON-Overlap => Cond1 Or Cond2 Or Cond3 Or Cond4

因此,重叠的充分条件是相反的。

Overlap => NOT (Cond1 Or Cond2 Or Cond3 Or Cond4)

德摩根定律说 不是(A或B或C或D)和不是A不是B不是C不是D是一样的 所以利用德·摩根,我们有

Not Cond1 And Not Cond2 And Not Cond3 And Not Cond4

这相当于:

A的左边到B的右边的左边,[RectA。左< RectB。正确的), A的右边到B的左边的右边,[RectA。对,>,RectB。左), A的顶部高于B的底部。Top > RectB。底), A的底部在B的顶部以下。底部< RectB。前)

Note 1: It is fairly obvious this same principle can be extended to any number of dimensions. Note 2: It should also be fairly obvious to count overlaps of just one pixel, change the < and/or the > on that boundary to a <= or a >=. Note 3: This answer, when utilizing Cartesian coordinates (X, Y) is based on standard algebraic Cartesian coordinates (x increases left to right, and Y increases bottom to top). Obviously, where a computer system might mechanize screen coordinates differently, (e.g., increasing Y from top to bottom, or X From right to left), the syntax will need to be adjusted accordingly/

其他回答

不要认为坐标表示像素的位置。把它们想象成像素之间。这样,2x2矩形的面积应该是4,而不是9。

bool bOverlap = !((A.Left >= B.Right || B.Left >= A.Right)
               && (A.Bottom >= B.Top || B.Bottom >= A.Top));

这是来自《Java编程入门-综合版》中的练习3.28。该代码测试两个矩形是否缩进,一个矩形是否在另一个矩形内,一个矩形是否在另一个矩形外。如果这些条件都不满足,则两者重叠。

**3.28(几何:两个矩形)编写一个程序,提示用户进入 中心x, y坐标,宽度和高度的两个矩形,并确定 第二个矩形是在第一个矩形的内部还是与第一个矩形重叠,如图所示 如图3.9所示。测试您的程序以覆盖所有情况。 下面是示例运行:

输入r1的中心x坐标,y坐标,宽度和高度:2.5 4 2.5 43 输入r2的中心x坐标,y坐标,宽度和高度:1.5 5 0.5 3 R2在r1里面

输入r1的中心x坐标,y坐标,宽度和高度:1 2 3 5.5 输入r2的中心x坐标,y坐标,宽度和高度:3 4 4.5 5 R2和r1重叠

输入r1的中心x坐标,y坐标,宽度和高度:1 2 3 3 输入r2的中心x坐标,y坐标,宽度和高度:40 45 3 2 R2不与r1重叠

import java.util.Scanner;

public class ProgrammingEx3_28 {
public static void main(String[] args) {
    Scanner input = new Scanner(System.in);

    System.out
            .print("Enter r1's center x-, y-coordinates, width, and height:");
    double x1 = input.nextDouble();
    double y1 = input.nextDouble();
    double w1 = input.nextDouble();
    double h1 = input.nextDouble();
    w1 = w1 / 2;
    h1 = h1 / 2;
    System.out
            .print("Enter r2's center x-, y-coordinates, width, and height:");
    double x2 = input.nextDouble();
    double y2 = input.nextDouble();
    double w2 = input.nextDouble();
    double h2 = input.nextDouble();
    w2 = w2 / 2;
    h2 = h2 / 2;

    // Calculating range of r1 and r2
    double x1max = x1 + w1;
    double y1max = y1 + h1;
    double x1min = x1 - w1;
    double y1min = y1 - h1;
    double x2max = x2 + w2;
    double y2max = y2 + h2;
    double x2min = x2 - w2;
    double y2min = y2 - h2;

    if (x1max == x2max && x1min == x2min && y1max == y2max
            && y1min == y2min) {
        // Check if the two are identicle
        System.out.print("r1 and r2 are indentical");

    } else if (x1max <= x2max && x1min >= x2min && y1max <= y2max
            && y1min >= y2min) {
        // Check if r1 is in r2
        System.out.print("r1 is inside r2");
    } else if (x2max <= x1max && x2min >= x1min && y2max <= y1max
            && y2min >= y1min) {
        // Check if r2 is in r1
        System.out.print("r2 is inside r1");
    } else if (x1max < x2min || x1min > x2max || y1max < y2min
            || y2min > y1max) {
        // Check if the two overlap
        System.out.print("r2 does not overlaps r1");
    } else {
        System.out.print("r2 overlaps r1");
    }

}
}

这是一个用c++快速检查两个矩形是否重叠的方法:

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

它的工作原理是计算相交矩形的左右边界,然后比较它们:如果右边界等于或小于左边界,这意味着交点是空的,因此矩形不重叠;否则,它将再次尝试顶部和底部边框。

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.

如果第一个比较有很高的错误几率,那么四个比较方法可能比这个方法更好。但这是非常罕见的,因为这意味着第二个矩形通常在第一个矩形的左边,而不是在右边或重叠;大多数情况下,您需要检查第一个矩形的两侧,这通常会使分支预测的优势失效。

根据矩形的预期分布,这种方法还可以进一步改进:

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

然而,如果相交的概率接近于不相交的概率,那么最好有一个完全无分支的替代方案:

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

(注意&&变成了一个&)

更容易检查一个矩形是否完全在另一个矩形之外,如果它是其中之一

在左边……

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

或者在右边…

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

或者在上面…

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

或者在底部…

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

对于第二个矩形,它不可能与它碰撞。因此,要有一个返回布尔值的函数,表示矩形是否碰撞,我们只需通过逻辑or组合这些条件,并对结果求反:

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

如果只在触摸时得到阳性结果,我们可以通过“<=”和“>=”来更改“<”和“>”。

设这两个矩形是矩形A和矩形b,设它们的中心为A1和B1 (A1和B1的坐标很容易求出来),设高为Ha和Hb,宽为Wa和Wb,设dx为A1和B1之间的宽度(x), dy为A1和B1之间的高度(y)。

现在我们可以说我们可以说A和B重叠,当

if(!(dx > Wa+Wb)||!(dy > Ha+Hb)) returns true