首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何绘制多个多边形的轮廓,同时在戈多中使用Geometry.merge_polygons_2d()时拥有一个共享边界的触摸多边形?

如何绘制多个多边形的轮廓,同时在戈多中使用Geometry.merge_polygons_2d()时拥有一个共享边界的触摸多边形?
EN

Stack Overflow用户
提问于 2022-06-18 01:51:02
回答 1查看 298关注 0票数 0

因此,目前,我采取的多边形数组,我想有一个轮廓,并把它放在一个"for“循环,然后发送给它一个轮廓抽屉枕木。鳕鱼看起来是这样的:

代码语言:javascript
复制
func _ready():
var provs = [$Polygon2D4,$Polygon2D,$Polygon2D3]
var outline_drawer = $outline_drawer
outline_drawer.color = Color(0.06,0.71,0.74) / Color(2,2,2)
var merge := []
var merged_provs := []
for p in range(provs.size()):
    var poly = provs[p]
    var points = poly.global_transform.xform(poly.polygon)
    merged_provs.append(points) 
var outlines_local := []
var global_to_local: Transform2D = outline_drawer.global_transform.affine_inverse()
for outline_global in merged_provs:
    outlines_local.append(global_to_local.xform(outline_global))
outline_drawer.outlines = outlines_local

下面是提纲抽屉的代码:

代码语言:javascript
复制
export(Color) var color = Color(0,0,0) setget set_color
export(float) var width = 1.5 setget set_width

var outlines = [] setget set_outlines

func _draw():
    for outline in outlines:
        for i in outline.size():
            draw_line(outline[i-1] , outline[i], color, width)

func set_color(value):
    color = value
    update()

func set_width(value):
    width = value
    update()

func set_outlines(value):
    outlines = value
    update()

结果是这样的,所以我想知道是否有一种方法来调整这段代码来合并多边形,这样就没有像在圆圈区域那样接触到的线?非常感谢所有的帮助!结果图片

EN

回答 1

Stack Overflow用户

发布于 2022-06-18 23:10:06

方法Geometry.merge_polygons_2d将返回多边形的Array (每个多边形都是PoolVector2Array)。

合并两个多边形可能不会导致多边形的原因。有两个案件需要注意:

  • 多边形一点也不碰。在这种情况下,Geometry.merge_polygons_2d将返回原始边界。
  • 多边形接触,但当你合并它们时,它们会留下一个或多个洞。所以戈多会返回外部的边界,然后是洞。

这些洞是多边形,其点按顺时针方向排列。边界是多边形,它们的点按逆时针方向排列。

为了正确地合并多个多边形,我们需要保持轨道边界和洞。考虑到第三个多边形可能覆盖或部分覆盖一个洞,我们必须…。

对于每个多边形:

  • 将其与先前的边界合并。从而产生新的边界和漏洞。
  • 从前面的洞中夹紧(减去)。这可能会消除这个洞。

当然,也有第三个多边形在现有边界之间架设桥梁的情况。我们也要处理那个案子。要做到这一点,我们需要检查它是否合并,我将检查结果中只有一个边界。

为了完成这个任务,我们需要从一个边界开始。所以我们可以直接把第一个合并到…但我会用一个空多边形。

再来一次。

我们有:

  • 一组边界(用空多边形初始化)。
  • 一组洞。

对于每个多边形:

  • 对于边界集中的每个边界:
    • 合并他们。这给了我们新的界限和漏洞。将这些洞添加到一组孔中。
    • 如果结果中只有一个边界:
      • 从边界集合中移除边界。
      • 用结果边界替换多边形。

代码语言:javascript
复制
- Else (they do not overlap): 
    - Do nothing (we are adding the polygon to the boundaries at the end).
  • 对于这套洞中的每个洞。
    • 将多边形从洞中夹紧。
    • 如果结果为空:-将孔从一组孔中移除。
    • 如果结果是单个项(多边形和洞不重叠,其中部分重叠):-用结果孔替换该孔。
    • 否则(原来多边形完全在洞内):-什么也不做(我们在最后将多边形添加到边界中)。

  • 将多边形添加到一组边界中。

嘿,那看起来就像源代码。我们快到了。

大的变化是,我们将是不同的操作通过循环。因为:

  • 在迭代时,我们不应该从集合中移除它们。因此,我们将向数组中添加我们想要删除的元素,这样我们就可以在最后删除它们。
  • 同样,我们也不会完全替换这个洞。我们将删除旧的,并添加新的。
  • 此外,由于边界部分可以添加洞,如果我们在做洞部分之前添加这些孔,那么我们就会浪费精力比较它们。

在执行操作之前,我正在将多边形转换为全局坐标。

我们将使用Geometry.is_polygon_clockwise来区分结果中的漏洞和边界。

当然,我们不需要写“什么都不做”的分支。

除此之外,这与上面的情况是一样的:

代码语言:javascript
复制
func _ready() -> void:
    # We have
    # - A set of boundaries (initialized with an empty polygon).
    var boundaries := [PoolVector2Array()]
    # - A set of holes.
    var holes := []

    # For each polygon:
    var polygons := [
        $Polygon1.global_transform.xform($Polygon1.polygon),
        $Polygon2.global_transform.xform($Polygon2.polygon),
        $Polygon3.global_transform.xform($Polygon3.polygon)
    ]
    for polygon in polygons:
        var boundaries_to_remove := []
        var holes_to_remove := []
        var holes_to_add := []

        # BOUNDARIES

        # - For each boundary in the set of boundaries:
        for boundary in boundaries:
            # - Merge them.
            var result := Geometry.merge_polygons_2d(polygon, boundary)
            var result_boundaries := []
            for result_polygon in result:
                if Geometry.is_polygon_clockwise(result_polygon):
                    # Hole
                    # Add the holes to the set of holes.
                    holes_to_add.append(result_polygon)
                else:
                    # Boundary
                    result_boundaries.append(result_polygon)

            # - If there is only one boundary in the result:
            if result_boundaries.size() == 1:
                # They merged
                # - Remove the boundary from the set of boundaries. (AFTER THE LOOP)
                boundaries_to_remove.append(boundary)
                # - Replace the polygon with the result boundary.
                polygon = result_boundaries[0]

        for boundary_to_remove in boundaries_to_remove:
            boundaries.erase(boundary_to_remove)

        # HOLES

        # - For each hole in the set of holes.
        for hole in holes:
            # - Clip the polygon from the hole.
            var result := Geometry.clip_polygons_2d(polygon, hole)
            # - If the result in empty:
            if result.size() == 0:
                # - Remove the hole from the set of holes. (AFTER THE LOOP)
                holes_to_remove.append(hole)
            
            # - If the result is single item
            if result.size() == 1:
                # - Replace the hole with the result hole. (AFTER THE LOOP)
                holes_to_remove.append(hole)
                holes_to_add.append(result[0])

        for hole_to_remove in holes_to_remove:
            holes.erase(hole_to_remove)

        for hole_to_add in holes_to_add:
            holes.append(hole_to_add)

        # ---

        # - Add the polygon to the set of boundaries.
        boundaries.append(polygon)

啊,对。我们应该画提纲。嗯,…我想洞和边界都会有,对吧?这应该可以做到:

代码语言:javascript
复制
    var outline_drawer := $outline_drawer
    var outlines_local := []
    var global_to_local:Transform2D = outline_drawer.global_transform.affine_inverse()
    for outline_global in holes:
        outlines_local.append(global_to_local.xform(outline_global))

    for outline_global in boundaries:
        outlines_local.append(global_to_local.xform(outline_global))

    outline_drawer.outlines = outlines_local

你可能有一些你认为是在同一条线上的东西,但实际上并非如此。我相信浮点错误会导致这一点。我希望这不是一个问题。

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

https://stackoverflow.com/questions/72666149

复制
相关文章

相似问题

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