避免布局算法中的振荡移动

时间:2014-06-16 16:50:42

标签: javascript algorithm layout geometry

继续这个问题:

Calculate distance to move a box to remove intersection

我有一个问题,移动一个盒子会导致它与另一个盒子重叠,而当前的算法只会将第一个盒子移回(几乎)它的方向,使它再次与第一个盒子重叠等等。有没有办法避免这种情况?我想要记住上次的矢量,并以某种方式将它与新建议的移动相结合可能是解决方案。

这是一个简单的小提琴:

http://jsfiddle.net/x8MT3/4/

注意一个盒子是如何移动的,但是然后与另一个盒子重叠,所以盒子再向相反的方向移动,经过6个周期后仍然重叠。

以下是add方法的代码 - 它将列表添加到列表中,检查当前成员是否有其他方法:

    self.add = function (item, iteration) {
        // check intersections with existing boxes
        iteration = iteration || 0;
        if (iteration < 6) {
            for (var i = 0; i < boxes.length; i++) {
                var stationary = boxes[i];
                var boundsA = getBounds(item);
                var boundsB = getBounds(stationary);
                if (doesIntersect(boundsA, boundsB)) {
                    item.elem.addClass("overlapped");
                    // move item
                    // 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: stationary.x + stationary.width / 2,
                        y: stationary.y + stationary.height / 2
                    };
                    var line = {
                        x1: centerA.x,
                        y1: centerA.y,
                        x2: centerB.x,
                        y2: centerB.y
                    }
                    var vector = {
                        x: Math.min(item.x + item.width, stationary.x + stationary.width) - Math.max(item.x, stationary.x),
                        y: Math.min(item.y + item.height, stationary.y + stationary.height) - Math.max(item.y, stationary.y)
                    };
                    var signX = line.x1 - line.x2 > 0 ? 1 : -1;
                    var signY = line.y1 - line.y2 > 0 ? 1 : -1;
                    item.x = item.x + vector.x * signX;
                    item.y = item.y + vector.y * signY;
                    item.elem.offset({
                        left: item.x,
                        top: item.y
                    });     
                    return self.add(item, iteration + 1);
                }
            }
        }
        boxes.push(item);
    }

1 个答案:

答案 0 :(得分:1)

为什么不使用迭代过程... ???

  • 因为我看到你要重新排列盒子以便它们不重叠
  • 但不要过多改变布局
  • 如果你不介意盒子之间的空间(不会碰到),那么:

box rearrange

算法:

1.找到重叠框

  • 红色框

2.找到移动方向

  • 绿色矢量
  • 在盒子中心之间
  • 然后将其大小更改为移动步骤(几个像素......)

3.计算重叠的新位置

  • 然后检查新的重叠
  • 如果距离另一个盒子太近,则停止向该方向移动
  • 蓝色箭头表示碰撞停止

4.对所有重叠的方框应用此方法(从项目符号1循环)

  • 只执行一个或几个步骤
  • 不是整个运动!!!

5.实际循环所有(来自子弹1)

  • 找不到重叠的框时停止
  • 或进程已超时...
  • 因为这也会卡住

[注释]

  • 如果盒子中心相同
  • 然后将随机方向添加到运动矢量
  • 整个过程可以应用更多次,减少步骤以提高速度