【问题标题】:What's wrong with my "intersects" algorithm?我的“相交”算法有什么问题?
【发布时间】:2013-12-25 17:02:31
【问题描述】:

与 Java AWT 的 Rectangle2D 类密切建模,我有我的 Rectangle POJO:

public class Rectangle {
    // The Coordinate of the upper-left corner of the Rectangle.
    private Coordinate upperLeft;   // upperLeft.getXVal() and upperLeft.getYVal()

    // The width of the Rectangle.
    private BigDecimal width;

    // The height of the Rectangle.
    private BigDecimal height;

    // Determine if we intersect otherRectangle.
    public boolean intersects(Rectangle otherRectangle) {
        BigDecimal x = otherRectangle.getUpperLeft().getXVal();
        BigDecimal y = otherRectangle.getUpperLeft().getYVal();
        BigDecimal w = otherRectangle.getWidth();
        BigDecimal h = otherRectangle.getHeight();
        BigDecimal x0 = getUpperLeft().getXVal();
        BigDecimal y0 = getUpperLeft().getYVal();

        if(isEmpty() || w.doubleValue() <= 0.0 || h.doubleValue() <= 0.0)
            return false;

        return (
            x.doubleValue() + w.doubleValue() > x0.doubleValue() &&
            y.doubleValue() + h.doubleValue() > y0.doubleValue() &&
            x.doubleValue() < x0.doubleValue() + getWidth().doubleValue() &&
            y.doubleValue() < y0.doubleValue() + getHeight().doubleValue()
        );
    }
}

当我执行以下代码时:

// r1 has upperLeft corner at (0,4), width = 6, height = 4
// r2 has upperLeft corner at (5,1), width = 2, height = 1
Rectangle r1 = new Rectangle(new Coordinate(0,4), 6, 4);
Rectangle r2 = new Rectangle(new Coordinate(5,1), 2, 1);

boolean result = r1.intersects(r2);

答案是错误的!在调试器中单步执行代码,我看到原因是因为返回值中的第二个AND 子句:

return (
    x.doubleValue() + w.doubleValue() > x0.doubleValue() &&
    y.doubleValue() + h.doubleValue() > y0.doubleValue() &&     <=== problem is here
    x.doubleValue() < x0.doubleValue() + getWidth().doubleValue() &&
    y.doubleValue() < y0.doubleValue() + getHeight().doubleValue()
);

上述代码运行时,y=1h=1y0=4。显然,1+1 &gt; 4false。所以这绝对是我算法的一个bug,但是我直接从Rectangle2D#intersect复制过来的,看不出哪里出错了。

【问题讨论】:

  • 但是您的两个示例矩形不相交。
  • 但是你的矩形相交...
  • 感谢@Edgar Boda (+1) - 但是怎么办? r1 的左上角为 (0,4),因此其所有坐标均为 (0,0)、(0,4)、(6,4) 和 (6,0)。 r2 的坐标是 (5,0)、(5,1)、(7,1) 和 (7,0)。 r2 在 r1 的右侧被“切成两半”
  • 你是减去高度和增加宽度......错了,你需要加上x+width和y+height。 r1 将是:(0,4), (6,4), (0,8), (6, 8) 和 r2 将是 (5,1),(7,1),(5,2),( 7,2)
  • 那么你需要像这样更改退货中的行:y.doubleValue() - h.doubleValue() &lt; y0.doubleValue()

标签: java algorithm geometry collision-detection intersection


【解决方案1】:

如果你想有一个左上角你需要检查以下条件以有一个交叉点:

以下任何一项都需要申请,您不会有交集:

  1. this.x + this.width
  2. other.x + other.width
  3. this.y - this.height > other.y(此矩形下方的其他矩形)
  4. other.y - other.height > this.y(此矩形上方的其他矩形)

所以要计算一个交点,你只需否定上面的:

return !( //notice the !
  x.doubleValue() + w.doubleValue() < x0.doubleValue() ||
  y.doubleValue() - h.doubleValue() > y0.doubleValue() ||     
  x0.doubleValue() + getWidth().doubleValue() < x.doubleValue() ||
  y0.doubleValue() - getHeight().doubleValue() > y.doubleValue()
); 

或者如果你想把NOT拉到里面:

 return (
  x.doubleValue() + w.doubleValue() >= x0.doubleValue() &&
  y.doubleValue() - h.doubleValue() <= y0.doubleValue() &&     
  x0.doubleValue() + getWidth().doubleValue() >= x.doubleValue() &&
  y0.doubleValue() - getHeight().doubleValue() <= y.doubleValue()
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多