Java方法仅使用左下点,宽度和高度来查找两个矩形相交的矩形?

Posted

技术标签:

【中文标题】Java方法仅使用左下点,宽度和高度来查找两个矩形相交的矩形?【英文标题】:Java method to find the rectangle that is the intersection of two rectangles using only left bottom point, width and height? 【发布时间】:2013-01-15 00:37:16 【问题描述】:

我找到了解决方案,但想确保我的逻辑是最有效的。我觉得有更好的方法。我有左下角的(x,y)坐标,2个矩形的高度和宽度,我需要返回第三个矩形,即它们的交点。我不想发布代码,因为我觉得这是作弊。

    我找出图表上最左边和最高的位置。 我检查一个是否与另一个完全重叠,然后反向查看另一个是否与 X 轴上的第一个完全重叠。 我检查 X 轴上的部分交叉点。 我基本上对 Y 轴重复步骤 2 和 3。 我做了一些数学运算并根据这些条件得到矩形的点。

我可能想多了,写出了低效的代码。我已经提交了一个工作程序,但想为我自己的知识找到最好的方法。如果有人可以同意或指出我正确的方向,那就太好了!

【问题讨论】:

我不知道这是否有帮助,但它涉及确定移动物体的碰撞点...example 非常感谢!我想这可能与此有关。我在互联网上找不到任何可以将其简化为我的具体示例的内容。希望我所做的足够接近高效。谢谢! 【参考方案1】:

为什么不使用 JDK API 来为您完成这项工作?

Rectangle rect1 = new Rectangle(100, 100, 200, 240);
Rectangle rect2 = new Rectangle(120, 80, 80, 120);
Rectangle intersection = rect1.intersection(rect2);

使用java.awt.Rectangle类,构造函数的参数为​​:x,y,width,height,其中x,y为矩形的左上角。您可以轻松地将左下角转换为左上角。


我推荐上面的,但如果你真的想自己做,你可以按照以下步骤操作:

say (x1, y1), (x2, y2) 分别是 Rect1 的左下角和右下角, (x3, y3), (x4, y4) 是 Rect2 的。

找到x1x3中较大的一个和x2x4中较小的一个,比如xLxR分别 如果xL >= xR,则不返回任何交集 找到y1y3中较大的一个和y2y4中较小的一个,比如yTyB分别 如果yT >= yB,则不返回任何交集 返回(xL, yB, xR-xL, yB-yT)

更类似于 Java 的伪代码:

// Two rectangles, assume the class name is `Rect`
Rect r1 = new Rect(x1, y2, w1, h1);
Rect r2 = new Rect(x3, y4, w2, h2);

// get the coordinates of other points needed later:
int x2 = x1 + w1;
int x4 = x3 + w2;
int y1 = y2 - h1;
int y3 = y4 - h2;

// find intersection:
int xL = Math.max(x1, x3);
int xR = Math.min(x2, x4);
if (xR <= xL)
    return null;
else 
    int yT = Math.max(y1, y3);
    int yB = Math.min(y2, y4);
    if (yB <= yT)
        return null;
    else
        return new Rect(xL, yB, xR-xL, yB-yT);

如您所见,如果您的矩形最初是由两个对角线定义的,那会更容易,您只需要做// find intersection 部分。

【讨论】:

我必须为作业执行此操作,否则我将只使用 jdk api。这与我的想法相似,但做得更好更简单。感谢您的意见! 我认为 int xR = Math.max(x2, x4) 和 int yB = Math.max(y2, y4) 都应该改成 Math.min(...) @WilliamMorrison,对不起各位,原来的伪代码与内联步骤不兼容,我已经更正了。 @user800183,对不起各位,原来的伪代码与内联步骤不兼容,我已经更正了。【参考方案2】:

我在一个小实用函数中确定两个矩形相交的变体。

//returns true when intersection is found, false otherwise.
//when returning true, rectangle 'out' holds the intersection of r1 and r2.
private static boolean intersection2(Rectangle r1, Rectangle r2,
        Rectangle out) 
    float xmin = Math.max(r1.x, r2.x);
    float xmax1 = r1.x + r1.width;
    float xmax2 = r2.x + r2.width;
    float xmax = Math.min(xmax1, xmax2);
    if (xmax > xmin) 
        float ymin = Math.max(r1.y, r2.y);
        float ymax1 = r1.y + r1.height;
        float ymax2 = r2.y + r2.height;
        float ymax = Math.min(ymax1, ymax2);
        if (ymax > ymin) 
            out.x = xmin;
            out.y = ymin;
            out.width = xmax - xmin;
            out.height = ymax - ymin;
            return true;
        
    
    return false;

【讨论】:

@rob 仔细阅读。 out 包含交叉点(如果存在)。甚至有文档解释说......此外,随着变量的命名更清楚,它更具可读性。让我知道是否可以为您解决任何其他问题。 呸!刚刚看到out 参数,所以如果你想进行名义上的改变是正确的,我将删除反对票。我仍然说它不是那么可读(请记住,您自己的代码总是可读的,这并不意味着其他人可以阅读它)但这是一个边界线宗教论点,这是我们正在谈论的数学。 这绝对是真的。我已经编辑了我的答案以删除 cmets 的可读性@rob 酷,虽然这个答案比公认答案正确的原因仍然不明显,但您可能还想详细说明一下。 float xmin = Math.max(r1.x, r2.x); Xmin 等于 Math.Max?这令人困惑【参考方案3】:

您也可以使用 Rectangle 源代码与自己的算法进行比较:

/**
 * Computes the intersection of this <code>Rectangle</code> with the
 * specified <code>Rectangle</code>. Returns a new <code>Rectangle</code>
 * that represents the intersection of the two rectangles.
 * If the two rectangles do not intersect, the result will be
 * an empty rectangle.
 *
 * @param     r   the specified <code>Rectangle</code>
 * @return    the largest <code>Rectangle</code> contained in both the
 *            specified <code>Rectangle</code> and in
 *            this <code>Rectangle</code>; or if the rectangles
 *            do not intersect, an empty rectangle.
 */
public Rectangle intersection(Rectangle r) 
    int tx1 = this.x;
    int ty1 = this.y;
    int rx1 = r.x;
    int ry1 = r.y;
    long tx2 = tx1; tx2 += this.width;
    long ty2 = ty1; ty2 += this.height;
    long rx2 = rx1; rx2 += r.width;
    long ry2 = ry1; ry2 += r.height;
    if (tx1 < rx1) tx1 = rx1;
    if (ty1 < ry1) ty1 = ry1;
    if (tx2 > rx2) tx2 = rx2;
    if (ty2 > ry2) ty2 = ry2;
    tx2 -= tx1;
    ty2 -= ty1;
    // tx2,ty2 will never overflow (they will never be
    // larger than the smallest of the two source w,h)
    // they might underflow, though...
    if (tx2 < Integer.MIN_VALUE) tx2 = Integer.MIN_VALUE;
    if (ty2 < Integer.MIN_VALUE) ty2 = Integer.MIN_VALUE;
    return new Rectangle(tx1, ty1, (int) tx2, (int) ty2);

【讨论】:

谢谢。可以根据我的需要轻松复制和粘贴。 +1。

以上是关于Java方法仅使用左下点,宽度和高度来查找两个矩形相交的矩形?的主要内容,如果未能解决你的问题,请参考以下文章

如何将图像从不规则矩形更改为矩形?

如何在不知道宽度或高度的情况下最好地对矩形的角进行排序?

在java中判断一个点是不是在一个有斜度的矩形内的 Rectangle的用法

C++编程!已知矩形,判断输入的点是不是包含在该矩形内。

查找/重新映射 OpenGL ES 坐标平面的边界

QT绘图二:动态绘制一个矩形