我目前正在为Unity开发一个基于节点的房屋建设者。该系统的工作流程非常简单:用户可以创建简单的多维数据集节点,并将它们相互连接以创建墙。网格处理已经完成,并且工作得很顺利。
我现在要做的是检测已创建的封闭空间的数量以及每个空间中涉及的顶点。可以在以下图像中看到可能的输入:
在第一张图片中,循环将是
(1,5,3,4),(1,2,6,8,7,5),(6,9,12,11,10,8),(8,10,14,13) (10,11,17,16,15,14)。
在第二个他们是
(1,2,5,6,8,7),(2,3,4,14,13,6,5),(6,13,12,11,10)和(8,6, 10,9)。
每个节点最多可以连接四个其他节点,每个节点一个节点,每个链接都存储在两侧。我不需要节点按任何特定顺序排列。
我以为我可以使用通用的循环检测算法并递归搜索子循环,直到我找到的循环没有内部连接,但这将非常耗费资源。必须有一些属性我可以用来检测没有内部连接的循环,而不会多次遍历图形,但我还没有找到它。
你有什么建议吗?
答案 0 :(得分:1)
要使以下算法起作用,您需要以下内容:
然后这个想法如下。取任何带有未使用边缘的节点,沿着任何未使用的边缘移动到邻居(记住方向)。这样做,立即按照使用的相应方向标记边缘。在这个邻居,你知道你来的方向。以逆时针顺序查看,直到找到第一个未使用的边缘(再次注意边缘方向)。您也可以按顺时针顺序搜索,这将定义所有输出面的顺序。例如。如果您来自左边缘,则分别检查底部,右侧和顶部边缘。穿过此边缘(标记为已使用)并重复,直到到达起始顶点。所有访问过的顶点都构成了你的房间。
这样做,您应该相应地更新未使用边的顶点列表。
最后,您还将为边框创建一个面。你可以检测到这个通过计算其方向:
v1 x v2 + v2 x v3 + v3 x v4 + ... + vn x v1
,其中v
是顶点的位置,x
表示叉积的z分量(代表面部方向):
(x1, y1) x (x2, y2) = (x1 * y2) - (x2 * y1)
此方向的边界面将与所有其他面具有不同的符号。实际符号取决于在边缘遍历期间是使用逆时针还是顺时针顺序。
答案 1 :(得分:1)
这只是第一个问题的答案,但它可能对第二个问题有所帮助。封闭房间的数量实际上有一个封闭的公式:
1 - V + E
其中V是顶点数,E是边数。在第二个示例中,有14个顶点,17个边和4个房间。
数学有点复杂,但关键词是Euler characteristic。