我有一个名为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};
以下是它们的外观:
我还有一个名为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/
答案 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;
}