[英]Merge all rectangles in an array with each other
I have an array of rectangles and I want to merge all overlapping and adjacent rectangles into each other.我有一个矩形数组,我想将所有重叠和相邻的矩形合并到一起。 The final array should have no overlapping or adjacent rectangles.
最终数组不应有重叠或相邻的矩形。 I tried doing the below code but some rectangles are still left over.
我尝试执行以下代码,但仍然遗留了一些矩形。
func combine_boxes(boxes: Array) -> void:
var merged := true
while merged:
merged = combine_all_overlapping_box(boxes)
func combine_all_overlapping_box(boxes: Array) -> bool:
var box: Rect2 = boxes[0]
# Remove our box
boxes.remove(0)
# Start from the back of the the array so removals are easier and don't invalidate the index
var merged := false
for j in range(boxes.size()-1, -1, -1):
var collider: Rect2 = boxes[j]
if overlap_adjacent(box, collider):
box = box.merge(collider)
# Remove collider box
boxes.remove(j)
merged = true
# Either add the merge box in, or the unaltered box we remove at the start
boxes.append(box)
return merged
This what I have been able to come up with:这是我能够想出的:
func combine_rects(rects: Array) -> Array:
var result := rects.duplicate()
var merged := true
while merged:
merged = false
rects = result
result = []
while rects.size() > 0:
var current_rect:Rect2 = rects.pop_back()
for index in for index in range(rects.size() - 1, -1, -1):
var other_rect:Rect2 = rects[index]
if current_rect.intersects(other_rect, true):
merged = true
current_rect = current_rect.merge(other_rect)
rects.remove(index)
result.append(current_rect)
return result
Let us look at the inner loop first:让我们先看看内部循环:
var current_rect:Rect2 = rects.pop_back()
for index in for index in range(rects.size() - 1, -1, -1):
var other_rect:Rect2 = rects[index]
if current_rect.intersects(other_rect, true):
merged = true
current_rect = current_rect.merge(other_rect)
rects.remove(index)
result.append(current_rect)
As you can see I remove an element from rects
and store it in current_rect
.如您所见,我从
rects
中删除了一个元素并将其存储在current_rect
中。 Then iterate over the rest of the elements, comparing it with them.然后遍历 rest 个元素,将其与它们进行比较。 I use
intersects
with true
as second argument so it also considers adjacent rects as intersecting… If they intersect, I merge them.我使用
intersects
with true
作为第二个参数,因此它也将相邻的矩形视为相交……如果它们相交,我将它们合并。 And also remove the other element with rects.remove(index)
… I iterate backwards so I don't have to adjust the index
.并且还删除了
rects.remove(index)
的另一个元素……我向后迭代,所以我不必调整index
。
Since I set the current_rect
with the result of the merge ( current_rect = current_rect.merge(other_rect)
), I can continue merging more rects into it in the same loop.因为我用合并的结果设置了
current_rect
( current_rect = current_rect.merge(other_rect)
),所以我可以在同一个循环中继续合并更多的 rect。
Finally I add whatever I ended up with to the result
.最后,我将最终结果添加到
result
中。
If we look at the mid loop, we see that I do this until I exhaust rects
:如果我们看一下中间循环,我们会看到我一直这样做,直到我用尽
rects
:
while rects.size() > 0:
var current_rect:Rect2 = rects.pop_back()
for index in for index in range(rects.size() - 1, -1, -1):
var other_rect:Rect2 = rects[index]
if current_rect.intersects(other_rect):
merged = true
current_rect = current_rect.merge(other_rect)
rects.remove(index)
result.append(current_rect)
Since I only remove from rects
(either by pop_back
or by remove
) it must eventually be empty and the loop ends.由于我只从
rects
中删除(通过pop_back
或通过remove
)它最终必须为空并且循环结束。
Now look at the broader picture:现在看看更广泛的图景:
func combine_rects(rects: Array) -> Array:
var result := rects.duplicate()
var merged := true
while merged:
merged = false
rects = result
result = []
while rects.size() > 0:
var current_rect:Rect2 = rects.pop_back()
for index in for index in range(rects.size() - 1, -1, -1):
var other_rect:Rect2 = rects[index]
if current_rect.intersects(other_rect):
merged = true
current_rect = current_rect.merge(other_rect)
rects.remove(index)
result.append(current_rect)
return result
We will continue looping as long as we merged something.只要我们合并了一些东西,我们就会继续循环。 The
merged
variable keeps track of that. merged
变量会跟踪它。 I set it to true
so the flow of execution enters the loop (the alternative would have been to make an infinite loop while true
and use break
).我将其设置为
true
以便执行流程进入循环(替代方案是while true
进行无限循环并使用break
)。
For the loop we need to make sure merged
starts false
, and result
is empty.对于循环,我们需要确保
merged
开始时为false
,并且result
为空。 So we do that.所以我们这样做。 But also, we want to iterate over the results of the past iteration.
而且,我们想要迭代过去迭代的结果。 Which is why I set
rects = result
.这就是我设置
rects = result
的原因。 And that means that I need the starting rects
in result
.这意味着我需要
result
中的起始rects
。 I took the opportunity to work on a copy ( var result:= rects.duplicate()
).我借此机会制作了一份副本(
var result:= rects.duplicate()
)。
You should be able to use it like this:你应该能够像这样使用它:
boxes = combine_rects(boxes)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.