如何处理重叠矩形的递归函数

时间:2014-07-14 16:33:51

标签: javascript recursion

我有一个名为myRects的矩形数组,如下所示:

const 
    r1 = {x1: 10, x2: 80, y1: 10, y2: 80},
    r2 = {x1: 60, x2: 100, y1: 60, y2: 100},
    r3 = {x1: 90, x2: 180, y1: 90, y2: 140},
    r4 = {x1: 120, x2: 140, y1: 130, y2: 160},
    r5 = {x1: 160, x2: 210, y1: 80, y2: 110},
    myRects = {r1: r1, r2: r2, r3: r3, r4: r4, r5: r5};

以下是它们的外观:

enter image description here

我还有一个名为doRectanglesIntersect(r1, r2)的便捷功能:

function doRectanglesIntersect(r1, r2) {
  return (r1.x1 <= r2.x2 &&
          r2.x1 <= r1.x2 &&
          r1.y1  <= r2.y2 &&
          r2.y1  <= r1.y2)
}

我想要的是一个名为recursivelyGetIntersectingRects(rect)的函数,它将返回一个与给定矩形相交的矩形数组或其相交的矩形 ad infinitum

因此,如果我将r1传递给此函数,我应该将[r2,r3,r4,r5]作为返回值,因为它们都已连接。我不介意这个函数是否返回对象文字或键,但它应该尽可能高效并且不返回重复值。

我能够制定这个问题,但解决方案让我感到安慰。我的思想不会递归地运作。

这是我制作的小提琴,其中包含上面的代码和画布图作为视觉辅助:http://jsfiddle.net/b3jX6/5/

3 个答案:

答案 0 :(得分:2)

我认为这样的事情可以做到:

iterativelyGetIntersectingRects(r, rects) {
 var inter = [];  // resulting intersecting rects
 var found = [r]; // found intersecting rects in last round (to be checked for subseq intersections)
 while(found.length) {   // while new ones found
  var a = found.shift(); // check this
  inter.push(a);         // also store to results
  var remain = [];
  while(rects.length) {      // while remaining for check
   var test = rects.shift(); // check next
   if( doIntersect(a, test))
    found.push(test);        // gotcha!
   else
    remain.push(test);       // not yet
  }
  rects = remain;            // remaining for check with next found
 }
 return inter;     
}

答案 1 :(得分:1)

编辑:从评论中抽象出一个完整的答案。

因为你正在努力使画布库更有效率,&#34;我建议你迭代而不是 recurse ; JS中的迭代速度更快,您不必担心递归深度。 More

然后问题变成了,&#34;如何快速检查矩形交叉点?&#34;有关详情,请参阅this SO post,但排名最高的答案目前在下面介绍了Daniel Vassalo的功能:

function intersectRect(r1, r2) {
  return !(r2.left > r1.right || 
           r2.right < r1.left || 
           r2.top > r1.bottom ||
           r2.bottom < r1.top);
}

...给出一个形式的矩形:

var sampleRectangle = {
  left:   10,
  top:    10,
  right:  30,
  bottom: 30
};

(对于寻求递归矩形重叠的人,请参阅此related C# SO question。)

答案 2 :(得分:0)

我选择了以下功能,这个功能受到快速答案的启发。

我进行了一些修改,因此没有修改底层集合,而是克隆了一系列rects。

function iterativelyGetIntersectingRects(r) {
    var intersectingRects = [],
        allRects = myRects.slice(0)
        foundStack = [r],
        foundRect, 
        i, 
        rectToTest, 
        remainingRectsToTest;

    while (foundStack.length > 0) {
        foundRect = foundStack.shift();
        intersectingRects.push(foundRect);
        remainingRectsToTest = [];
        for (i = 0; i < allRects.length; i++) {
            rectToTest = allRects[i];
            if (doRectanglesIntersect(foundRect, rectToTest)) {
                foundStack.push(rectToTest);
            } else {
                remainingRectsToTest.push(rectToTest)
            }
        }
        allRects = remainingRectsToTest;
    }

    intersectingRects.shift(); // This is our original rectangle

    return intersectingRects;
}