首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >(戈多引擎)用几何的merge_polygons_2d()方法合并多个多边形

(戈多引擎)用几何的merge_polygons_2d()方法合并多个多边形
EN

Stack Overflow用户
提问于 2021-05-06 04:57:14
回答 1查看 828关注 0票数 3

考虑到以下场景:给定n个类似于“阴影”的Polygon2D节点(带有减半alpha值的黑色),如何使用merge_polygons_2d()方法将所有这些节点组合成一个单一的Polygon2D节点?

三个叠加多边形的例子。

使用以下硬编码代码,我成功地将所有三个多边形合并为一个.但我想不出如何通过迭代来自动化这个过程,以避免我的方法在这种情况下可能会超过10。20..例如,要合并的多边形。

代码语言:javascript
复制
func Merge_Map_Shadows() -> void:
# Get all "shadow" polygons and store them in an array,
# then apply xform transform in order to retain it's position and rotation.
# After that, delete the original shadow.
if Map_Shadows.get_child_count() > 0:
    var _detected_shadows: Array = []
    for _shadow in Map_Shadows.get_children():
        var _transformed_polygon: PoolVector2Array = []
        for _vector in _shadow.polygon: _transformed_polygon.append(_shadow.transform.xform(_vector))
        _detected_shadows.append(_transformed_polygon)
        _shadow.call_deferred("queue_free")
    
    # Create the "master shadow" node
    var _master_shadow: Polygon2D = Polygon2D.new() ; _master_shadow.color = Color.black ; _master_shadow.color.a = 0.5
    
    # Manually merge two "shadows" to the third and than apply the result to the master node
    var _merged_shadow_1: Array = []
    var _merged_shadow_2: Array = []
    _merged_shadow_1 = Geometry.merge_polygons_2d(_detected_shadows[0], _detected_shadows[2])
    _merged_shadow_2 = Geometry.merge_polygons_2d(_merged_shadow_1[0], _detected_shadows[1])
    _master_shadow.set_polygon(_merged_shadow_2.front())
    
    Map_Shadows.add_child(_master_shadow)

结果正是我所期望的。

在节点结构上的多边形合并过程之前和之后。

谢谢你迈克。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-06 07:48:45

因为您是作为同一节点的子节点移除和添加的。我将利用这份儿童名单。

在我们开始之前,我们需要记住几件事:

Polygon2D.

  • Not不是所有的节点都是Polygon2D重叠的。

  • Polygon2D节点可能应用了非身份转换。

计划是将多边形合并到适当的位置。我会列出需要删除的多边形。以后就会恢复到那种状态了。

让我们首先迭代一遍儿童的列表。我使用整数索引是出于以后才有意义的原因,所以我有:

代码语言:javascript
复制
for child_index in Map_Shadows.get_child_count():
    pass

我们当然需要孩子,所以:

代码语言:javascript
复制
for child_index in Map_Shadows.get_child_count():
    var child = Map_Shadows.get_child(child_index)

但是我们需要确保它是一个Polygon2D

代码语言:javascript
复制
for child_index in Map_Shadows.get_child_count():
    var child = Map_Shadows.get_child(child_index)
    var found_polygon:Polygon2D = child as Polygon2D
    if found_polygon == null:
        continue

此外,由于我们将从同一列表中删除,我们需要考虑的是,它可能会排队等待删除:

代码语言:javascript
复制
for child_index in Map_Shadows.get_child_count():
    var child = Map_Shadows.get_child(child_index)
    var found_polygon:Polygon2D = child as Polygon2D
    if found_polygon == null or found_polygon.is_queued_for_deletion():
        continue

接下来,我们需要检查子程序是否已应用了非标识转换,如果应用了,则撤消它:

代码语言:javascript
复制
if found_polygon.transform != Transform2D.IDENTITY:
    var transformed_polygon = found_polygon.transform.xform(found_polygon.polygon)
    found_polygon.transform = Transform2D.IDENTITY
    found_polygon.polygon = transformed_polygon

注意,我们不需要对多边形的点进行迭代。

现在,我们将尝试将多边形与我们已经看到的所有多边形合并。要做到这一点,我们需要另一个循环。它看起来就像第一个,只是上升到了当前的指数。这就是为什么我要用一个索引来迭代。

代码语言:javascript
复制
    for child_subindex in child_index:
        var other_child = Map_Shadows.get_child(child_subindex)
        var other_found_polygon:Polygon2D = other_child as Polygon2D
        if other_found_polygon == null or other_found_polygon.is_queued_for_deletion():
            continue

现在我们尝试合并:

代码语言:javascript
复制
        var merged_polygon = Geometry.merge_polygons_2d(found_polygon.polygon, other_found_polygon.polygon)

如果它们合并了,我们就会得到一个带有单个项(合并多边形)的数组,如果不是这样的话,它们就不会合并。因此:

代码语言:javascript
复制
    if merged_polygon.size() != 1:
        continue

最后,当它们合并时,我们将移除当前的多边形(好的,我们将它放在一个数组中,以便稍后删除它),并将另一个多边形设置为合并的多边形:

代码语言:javascript
复制
    other_found_polygon.polygon = merged_polygon[0]
    polygons_to_remove.append(found_polygon)
    break

我在这里中断,因为我们已经找到了一个多边形来合并当前的多边形。不用再找了。

当然,一次通过多边形可能不会完成所有的合并。因此,将整个过程放入一个while(true)循环中,如下所示:

代码语言:javascript
复制
var polygons_to_remove:Array
while(true):
    polygons_to_remove = []

    # the rest of the code here

    if polygons_to_remove.size() == 0:
        break

    for polygon_to_remove in polygons_to_remove:
        polygon_to_remove.queue_free()

正如我在一开始所说的,我们保留了一个需要删除的多边形列表(嗯,一个数组)。

如果我们没有合并任何多边形,那么我们也不必删除任何多边形。这意味着我们完蛋了。这就是为什么当要删除的多边形列表为空时,我们退出了while(true)循环。

当然,如果列表不是空的,我们实际上需要删除这些节点。所以给他们打电话叫queue_free。不,我们不需要call_deferred,事实上,我们不需要call_deferred,因为我们正在检查is_queued_for_deletion,所以我们需要它们立即排队。

因为人们喜欢复制和粘贴,这是完整的相关代码:

代码语言:javascript
复制
var polygons_to_remove:Array
while(true):
    polygons_to_remove = []
    for child_index in Map_Shadows.get_child_count():
        var child = Map_Shadows.get_child(child_index)
        var found_polygon:Polygon2D = child as Polygon2D
        if found_polygon == null or found_polygon.is_queued_for_deletion():
            continue

        if found_polygon.transform != Transform2D.IDENTITY:
            var transformed_polygon = found_polygon.transform.xform(found_polygon.polygon)
            found_polygon.transform = Transform2D.IDENTITY
            found_polygon.polygon = transformed_polygon

        for child_subindex in child_index:
            var other_child = Map_Shadows.get_child(child_subindex)
            var other_found_polygon:Polygon2D = other_child as Polygon2D
            if other_found_polygon == null or other_found_polygon.is_queued_for_deletion():
                continue

            var merged_polygon = Geometry.merge_polygons_2d(found_polygon.polygon, other_found_polygon.polygon)
            if merged_polygon.size() != 1:
                continue

            other_found_polygon.polygon = merged_polygon[0]
            polygons_to_remove.append(found_polygon)
            break

    if polygons_to_remove.size() == 0:
        break

    for polygon_to_remove in polygons_to_remove:
        polygon_to_remove.queue_free()

是的,我测试过那个东西。它起作用了。然而,我假设这些都是行为良好的多边形。可能会有边缘病例。特别是,我没有使用少于三个顶点的Polygon2D进行测试,没有用invert_enable__的Polygon2D测试,也没有用polygons集的Polygon2D进行测试(参见)。

我还可以考虑进一步的优化:我们只需要检查合并在前一次传递中的多边形之间的进一步合并。如果一个多边形完成了一个没有合并的传递,这意味着它是孤立的,并且我们不需要一直检查那个。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67412060

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档