【问题标题】:What's wrong with my "contains" algorithm?我的“包含”算法有什么问题?
【发布时间】:2013-12-25 20:24:29
【问题描述】:

与 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 wholly contains otherRectangle. (no touching sides).
    @Override
    public boolean contains(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(isSingularity() || w.doubleValue() <= 0.0 || h.doubleValue() <= 0.0)
            return false;

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

当我执行以下代码时:

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

boolean result = r1.contains(r2);

答案是错误的!

注意,我写这篇文章是基于以下假设:

  • upperLeft 坐标字段就是——矩形的左上角;这意味着:
  • 获取右上角坐标的伪代码为(upperLeft.x + width, upperLeft.y)
  • 获取左下角坐标的伪代码为(upperLeft.x, upperLeft.y - height)
  • 获取右下角坐标的伪代码为(upperLeft.x + width, upperLeft.y - height)

那么,我认为我的返回值有些问题:

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

但我不知道我哪里出错了。有任何想法吗?

【问题讨论】:

  • 尝试将返回语句拆分为多个值,看看哪个是错误的。
  • 为什么这被否决了?它显示了一个SSCCE,是原创的、易于处理的并且显然是一个编程问题。
  • @TicketMonster 我添加了一个图表来帮助理解,请检查是否有帮助。

标签: java algorithm geometry


【解决方案1】:

您的y 不等式混淆了。因为您使用左上角作为起点,所以您需要检查负方向的遏制。

上图绘制了r1(绿色)和r2(粉色)。要修复您的代码,请进行以下调整

// y must be less than y0
y.doubleValue() <= y0.doubleValue()

// y - h must be greater than y0 - h0
(y.doubleValue() - h.doubleValue()) >= (y0.doubleValue() - getHeight().doubleValue())

【讨论】:

    【解决方案2】:

    您似乎混淆了两个不同的坐标系。您的代码使用 Y 轴从上到下指向的坐标系(这通常用于计算机图形学中)。同时,您的 cmets 指的是 Y 轴从下到上指向的标准数学坐标系。

    这就是为什么您的代码无法按您预期的方式运行的原因。

    您需要决定使用哪个坐标系,然后修复代码或更改您在头脑中计算坐标的方式。

    【讨论】:

    • @NPE 怎么样?如果 r1 的 左上角 为 (0,4),则必须加上宽度并减去高度才能得到其他坐标。这意味着它的其他 3 个坐标将是 (0,0)、(6,0) 和 (6,4)。如果你对 r2 做同样的事情,那么它的坐标是 (1,1), (1,2), (2,2) 和 (2,1)...
    • @TicketMonster 如果左上角是 (0, 4),为什么要减去高度来得到其他坐标?
    • 在正常的数学上下文中我会同意,但在 Java-2D-Context 中,原点位于左上角,因此 y 轴是倒置的,并且 r1 不包含 r2。跨度>
    • 我很困惑大家!如果左上角为 (0,4),则它表示矩形的最顶部(y 轴方向)和最左侧(x 轴方向)坐标。因此,您添加宽度以获得右上和右下 x 值,并减去高度以获得左下和右下 y 值。因为它是上角,所以它说“矩形中没有任何东西在我的左边,矩形中没有任何东西比我高”。
    • @TicketMonster:您混淆了两个不同的坐标系。查看更新的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 2021-02-27
    • 2011-12-03
    • 2016-09-19
    • 1970-01-01
    相关资源
    最近更新 更多