计算移动框以移除交叉点的距离

时间:2014-06-13 15:42:36

标签: javascript algorithm geometry

我有两个重叠的盒子,我想知道如何移动一个去除交叉点。

我从一个盒子的中心到另一个盒子的中心定义了一个向量,并沿着该行移动一个盒子,但这可能比它需要移动的更远,或者可能不够远。因此,我认为我需要做的是找出最靠近中心线之间的固定箱线的哪个角,然后计算出该角落的那条线(或可能超出该线的距离)的距离。然后我可以按照这个数量复制我的矢量,但是我很难绕过它。

以下是我目前所拥有的内容,我添加了xywidthheight属性的项目列表,当我添加每个项目时,我正在检查列表中已有项目的交叉点。如果找到了交叉点,我会尝试移动新项目,然后再试一次:

function BoxList() {
    var self = this;
    var boxes = [];

    self.add = function(item, iteration) {
        // check intersections with existing boxes
        iteration = iteration || 0;
        if (iteration < 5) {
            for (var i=0; i < boxes.length; i++) {
                if (doesIntersect(getBounds(item),getBounds(boxes[i]))) {
                    item.elem.addClass("overlapped");
                    // Find vector from mid point of one box to the other
                    var centerA = { x: item.x + item.width / 2, y: item.y + item.height / 2 };
                    var centerB = { x: boxes[i].x + boxes[i].width / 2, y: boxes[i].y + boxes[i].height / 2 };
                    var line = { x1 : centerA.x, y1 : centerA.y, x2 : centerB.x, y2 : centerB.y };
                    var vector = { x : line.x1 - line.x2, y: line.y1 - line.y2 };
                    item.x = item.x + vector.x;
                    item.y = item.y + vector.y;
                    item.elem.offset({ left: item.x , top: item.y });       // TODO: calculate size of move needed
                    return self.add(item, iteration + 1);
                }
            }
        }
        boxes.push(item);
    }

    function getBounds(item) {
        return { x1: item.x, x2: item.x + item.width, y1: item.y, y2: item.y + item.height };
    }

    function doesIntersect(a,b) {
        return a.x1 < b.x2 && a.x2 > b.x1 && a.y1 < b.y2 && a.y2 > b.y1;
    }
}

这是一个简单的fiddle

单击“移动”以尝试排列这两个框,请注意重叠框被移动两次并且移动得比实际需要的更远。

有什么想法?关于更好地解决这个问题的建议也非常感谢。

1 个答案:

答案 0 :(得分:1)

正如我现在读到的那样,你计算两个盒子的中心并使用这两个点来制作推动其中一个盒子的向量。那是错误的载体。如果您将方框放在彼此的顶部,那么该向量将为(0,0)。如果这些方框只是互相夹住,那么向量将处于最高可能值。

你可以看到幽灵的这种行动。首先它只会被推动一点点,然后它会被推得很多。

相反,您需要的矢量应该基于重叠的大小。如果重叠是20px乘30px,则向量为(+20,+30)

var vector = {
    x: Math.min(box1.x + box2.width, box2.x + box2.width) - Math.max(box1.x, box2.x),
    y: Math.min(box1.y + box2.height, box2.y + box2.height) - Math.max(box1.y, box2.y)
}

vector.x是边界框的右上角减去边界框的左下角。同意vector.y

这会将框移动恰当的数量:http://jsfiddle.net/x8MT3/2/

我添加了一个需要2次迭代的第3个盒子对,可能顶盒应该向另一个方向移动。我设置的向量始终为(+,+),您可以进行中心点计算以确定每个方向应该有哪个符号。