Delaunay三角形点连接?

时间:2015-06-13 12:54:43

标签: java libgdx triangulation procedural-generation

我正在观看此视频:Delaunay Triangulation我希望以同样的方式使用它来生成程序内容。我很难弄清楚如何使用DelaunayTriangulation提供的LibGDX类,但我想我终于明白了。

然而,我的问题是如何以简单的方式知道哪一点与哪个点相关?这就是我目前设置测试点的方法,这些点最终需要由生成的房间提供。

private void TriangleTest()
    {
        DelaunayTriangulator triangulator = new DelaunayTriangulator();

        points = new float[8];
        points[0] = 80;
        points[1] = 30;
        points[2] = 40;
        points[3] = 45;
        points[4] = 0;
        points[5] = 10;
        points[6] = -100;
        points[7] = 100;

        indices = triangulator.computeTriangles(points, false);

        System.out.println(indices);
        //Output [1, 0, 2, 1, 2, 3]
    }

这就是我绘制点和线/三角形的方式,仅用于可视化和理解。

private void DrawTriangles()
    {
        //Draw points
        for (int i = 0; i < points.length / 2; i++)
        {
            DebugHelper.DrawDebugPoint(new Vector2(points[i * 2], points[i * 2 + 1]), camera.combined);
        }

        //Draw lines
        for (int i = 0; i < indices.size / 3; i++)
        {
            Vector2 v1 = new Vector2(points[indices.get(i * 3) * 2],
                    points[indices.get(i * 3) * 2 + 1]);
            Vector2 v2 = new Vector2(points[indices.get(i * 3 + 1) * 2],
                    points[indices.get(i * 3 + 1) * 2 + 1]);
            Vector2 v3 = new Vector2(points[indices.get(i * 3 + 2) * 2],
                    points[indices.get(i * 3 + 2) * 2 + 1]);

            DebugHelper.DrawDebugLine(v1, v2, camera.combined);
            DebugHelper.DrawDebugLine(v2, v3, camera.combined);
            DebugHelper.DrawDebugLine(v3, v1, camera.combined);
        }
    }

假设我正确使用此功能(正确绘制了点和三角形)我正在绘制双线:

[1, 0, 2] //1st indices (2nd point connects to 1st point)
[1, 2, 3] //2nd indices (1st point connects to 2nd point)

那么有什么方法可以过滤掉这些吗?因为我只对连接感兴趣而不是实际上并排绘制三角形来生成网格。

此外,在the video I mentioned on top中你注意到有一些线被删除,以便在电影中50秒内有一些死亡结束。这是怎么计算的?有些也变色了,它留下了死胡同和循环的混合物。我很想知道如何实现这一目标。

3 个答案:

答案 0 :(得分:2)

我是原始问题中链接的视频的作者。视频中演示的源代码可在此处找到:https://bitbucket.org/NathisGreen/pcgdungeons

这是我大学最后一年的一部分,所以我有一份详细的报告,解释了整个过程的工作原理,可以在这里阅读: http://www.nathanmwilliams.com/files/AnInvestigationIntoDungeonGeneration.pdf

第2.3.2节和第4.1节涉及这里讨论的Delaunay三角剖分。

但基本上所有发生创建最终图形的事情,都是找到由三角剖分产生的图形的最小生成树,然后将原始图形中的一些边缘随机地添加到最小生成树图形中。 / p>

答案 1 :(得分:1)

您似乎只想计算生成三角形的集。因此,您只需创建一个Edge类,其中包含两个特殊属性:

  • equals方法返回true即使要比较的边缘的顶点被交换(这样边缘(2,1)将被视为与边缘{{“相等”{ 1}})
  • (1,2)方法的实施方式与此hashCode实施方式一致,如Object#hashCode文档中所述:

      

    如果两个对象根据equals(Object)方法相等,则对两个对象中的每个对象调用hashCode方法必须生成相同的整数结果。

  •   
  这样,这些equals对象可以简单地放入EdgeSet将处理其余的:即使添加了“重复”边,该集最终也会包含每个边缘只有一次。

Set

上述程序将打印

import java.util.LinkedHashSet;
import java.util.Set;

public class DelaunayEdges
{
    public static void main(String[] args)
    {
        int triangleIndices[] = new int[] { 1, 0, 2, 1, 2, 3 };
        Set<Edge> edges = computeEdges(triangleIndices);
        System.out.println("Edges: "+edges);
    }

    static class Edge
    {
        private final int vertex0;
        private final int vertex1;
        public Edge(int vertex0, int vertex1)
        {
            this.vertex0 = vertex0;
            this.vertex1 = vertex1;
        }
        @Override
        public String toString()
        {
            return "("+vertex0+","+vertex1+")";
        }
        @Override
        public int hashCode()
        {
            return vertex0 ^ vertex1;
        }
        @Override
        public boolean equals(Object object)
        {
            if (this == object)
            {
                return true;
            }
            if (object == null)
            {
                return false;
            }
            if (getClass() != object.getClass())
            {
                return false;
            }
            Edge that = (Edge) object;
            return 
                (this.vertex0 == that.vertex0 &&
                 this.vertex1 == that.vertex1) ||
                (this.vertex0 == that.vertex1 &&
                 this.vertex1 == that.vertex0);
        }
    }

    private static Set<Edge> computeEdges(int triangleIndices[])
    {
        Set<Edge> edges = new LinkedHashSet<Edge>();
        for (int i=0; i<triangleIndices.length; i+=3)
        {
            int i0 = triangleIndices[i+0];
            int i1 = triangleIndices[i+1];
            int i2 = triangleIndices[i+2];
            edges.add(new Edge(i0, i1));
            edges.add(new Edge(i1, i2));
            edges.add(new Edge(i2, i0));
        }
        return edges;
    }
}

因此,省略边Edges: [(1,0), (0,2), (2,1), (2,3), (3,1)] ,因为它被认为等于边(1,2)

(当然,人们可以将这个集合转换回普通的(2,1)边缘索引数组,但这不是问题的重点)

答案 2 :(得分:0)

IMO无法知道何时没有解释或示例代码。但是可以使用轮廓线作为迷宫。以下是如何将其与最小生成树(https://twitter.com/nathanpie/status/435558377964318720)一起使用的说明。 BTW。 delaunay三角剖分是最小生成树的超集。