如何将几何体分成块?

时间:2015-06-03 22:21:13

标签: algorithm computational-geometry partitioning

我确信已经有一些算法可以满足我的需求,但我不确定谷歌会使用什么词组,或算法类别是什么。

这是我的问题:我有一个由多个接触块(hyperslabs)组成的多面体,i。即边缘是轴对齐的,边缘之间的角度是90°。多面体内部可能有孔。

我想将这个凹面多面体分解成一个小的凸矩形轴对齐的整块是可能的(如果原始多面体是凸的并且没有孔,则它已经是这样的块,因此,解决方案)。为了说明,我制作了一些二维图像(但我需要3-D的解决方案,最好是N-D):

我有这个几何:

Original

一个可能分解成块的是:

Possible

但我想要的是这个(尽可能少的块):

Correct

我的印象是精确的算法可能太贵了(这个问题是NP难的?),所以近似算法是合适的。

一个可能使问题更容易的细节,因此可能有一个更合适/专门的算法是所有边都有一些固定值的大小倍数(你可能认为所有边大小都是整数,或者说几何由均匀的小方块或体素组成。

背景:这是PDE域的结构化网格离散化。

什么算法可以解决这个问题?我应该选择哪种算法 搜索?

5 个答案:

答案 0 :(得分:3)

更新:在你回答这个问题之前,我想指出我的答案略微偏离主题。原始海报有关于多面体分解的问题,这些多面体具有轴对齐的面。鉴于这种多面体,问题是将其分解为凸面部分。问题是3D,可能是nD。我的答案是关于一般多面体的分解。因此,当我给出给定实现的答案时,该答案适用于多面体轴对齐的特殊情况,但可能是对于轴对齐的多面体存在更好的实现。当我的回答说通用多面体的问题是NP完全时,可能存在针对轴对齐多面体的特殊情况的多项式解。我不知道。

现在这是我的(稍微偏离主题)答案,低于横向规则......

CGAL C++ library有一个算法,给定2D多边形,可以计算该多边形的最佳凸分解。该方法在the part 2D Polygon Partitioning of the manual中提到。该方法名为CGAL::optimal_convex_partition_2。我引用手册:

  

此函数提供Greene's dynamic programming algorithm for optimal partitioning [2]的实现。在最坏的情况下,该算法需要O(n 4 )时间和O(n 3 )空间。

bibliography of that CGAL chapter中,文章[2]是:

  

[2] Daniel H. Greene。多边形分解为凸起部分。在Franco P. Preparata编辑, Computational Geometry Adv。的第1卷。 COMPUT。 Res。,第235-259页。 JAI Press,Greenwich,Conn。,1983。

这似乎正是您所寻找的。

请注意,CGAL手册的同一章也提到了在O(n)中运行的近似值,因此不是最优的:CGAL::approx_convex_partition_2

编辑,关于3D案例:

在3D中,CGAL有another chapter about Convex Decomposition of Polyhedra。本章的第二段说“已知这个问题是NP难的[1]”。参考文献[1]是:

  

[1] Bernard Chazelle。多面体的凸分区:下界和最坏情况下的最优算法。 SIAM J. Comput。,13:488-507,1984。

CGAL有一个方法CGAL::convex_decomposition_3来计算非最佳分解。

答案 1 :(得分:2)

我觉得你的问题是NP难的。我建议第一步可能是将图形分成沿所有超平面的子矩形。因此,在您的示例中,将有三个超平面(线)和四个生成的矩形。然后问题变成将矩形重新组合成更大的矩形以最小化矩形的最终数量。也许0-1整数编程?

答案 2 :(得分:1)

我认为动态编程可能是你的朋友。

我看到的第一步是将多面体划分为一个简单的块集合,这样每个可能的面都可用(即切片并将其切成最小的块)。这应该是微不足道的,因为所有东西都是轴对齐的盒子,因此类似k树的解决方案就足够了。

这似乎是合理的,因为我可以看看它的成本。这样做的代价是我忘了" hyperslabs的原始配置,选择用一组新的hyperslabs替换它。这可能导致我误入歧途的唯一方法是,原始配置是否可以为解决方案提供一些东西。鉴于你想要一个"最佳"对于所有配置的解决方案,我们必须假设原始结构不是非常有用。我不知道是否可以证明这些原始信息是无用的,但我会在这个答案中做出这样的假设。

现在问题已经减少为类似于受限制的生成林问题的图形问题。我认为查看问题的最自然的方法是将其视为图形着色问题(只要你可以避免将它与更着名的图形着色问题混淆,即在没有相同颜色共享的两种状态的情况下尝试着色地图边框)。我有一个节点图(小块),我希望每个节点都分配一种颜色(最终将是" hyperslab"它涵盖了该块)。我有约束,我必须在hyperslab形状中分配颜色。

现在一个关键的观察是,并非所有可能性都必须考虑。拍摄我们想要看到的最终彩色图表。我们可以通过将任何穿过分区的hyperslab分成两部分来以任何方式对该图进行分区。但是,并非每个分区都有意义。唯一有意义的分区是轴对齐切割,它总是将超级圆柱体分成两个超级圆柱体(与切割不是轴对齐时可能出现的任何更复杂的形状相反)。

现在这种削减与我们真正试图解决的问题相反。切割实际上是我们在第一步中所做的事情。虽然我们想要找到最佳合并算法,但要撤消这些切割。但是,这显示了我们将在动态编程中使用的一个关键特性:合并的唯一特征是在切割的暴露表面上。一旦找到形成中心区域的最佳方式,它通常不会在算法中起作用。

因此,让我们首先构建一个超大空间的集合,这些空间不仅可以定义普通的超级散列,而且可以定义任何超大空间的配置,例如带有空洞的超级空间。每个超文本空间记录:

  • 其中包含的叶子超大数量(这是我们最终试图最小化的数量)
  • hyperslabs的内部配置。
  • hyperslab-space表面的地图,可用于合并。

然后我们定义一个" merge"规则将两个或多个相邻的超大空间变成一个:

  • Hyperslab-spaces只能组合成新的hyperslab-spaces(所以你需要组合足够的碎片来创建一个新的hyperslab,而不是一些更奇特的形状)
  • 简单地通过比较表面来完成合并。如果存在具有匹配维度的特征,则将它们合并(因为显示如果特征匹配,则总是更好地合并超文本而不是合并)

现在这足以用暴力解决问题了。解决方案肯定是NP完全的。但是,我们可以添加一个额外的规则,这将大大降低这个成本:"一个超级空间被认为是更好的'如果它们覆盖相同的空间,并且在它们的表面上具有完全相同的特征,则比另一个。在这种情况下,其中内部较少的超梁是更好的选择。"

现在的想法是,在算法的早期,你必须跟踪各种组合,以防万一它们是最有用的。然而,随着合并算法使事情变得越来越大,内部细节将不太可能暴露在hyperslab空间的表面上。考虑

+===+===+===+---+---+---+---+
|   :   : A | X :   :   :   :
+---+---+---+---+---+---+---+
|   :   : B | Y :   :   :   :
+---+---+---+---+---+---+---+
|   :   :   |   :   :   :   :
+===+===+===+   +---+---+---+

看看左侧的盒子,我已经冒了更强的线条标记。在将盒子与世界其他地方合并时,AB:XY表面就是最重要的。因此,只有少数合并模式可以在此表面发生

  • 无法合并
  • 答:X允许合并,但B:Y不能
  • B:Y允许合并,但A:X不能
  • A:X和B:Y允许合并(两个独立合并)
  • 我们可以合并一个更大的正方形,AB:XY

有很多方法可以覆盖3x3平方(至少几十个)。但是,我们只需要记住实现每个合并过程的最佳方法。因此,一旦我们在动态编程中达到这一点,我们就可以忘记可能发生的所有其他组合,并且只关注实现每组表面特征的最佳方法。

事实上,这为一个简单的贪婪算法设置了问题,该算法探索了哪些合并为减少hyperslabs的数量提供了最好的承诺,总是记住实现给定的一组表面特征的最佳方法。当算法完成合并时,无论最终的hyperslab空间包含什么,都是最佳布局。

我不知道它是否可证明,但我的直觉认为这将是一个O(n ^ d)算法,其中d是维数。我认为最糟糕的解决方案就是收集hyperslabs,当它们组合在一起时,形成一个巨大的hyperslab。在这种情况下,我相信算法最终会以k-tree算法的反向运行。再一次,没有给出证据......这只是我的直觉本能。

答案 3 :(得分:0)

您可以尝试约束delaunay三角测量。它只提供很少的三角形。

答案 4 :(得分:0)

您能够确定每条线的方程式吗? 如果是这样,也许你可以得到这些线之间的交点(点)。然后,如果您采用一个轴,并开始寻找具有两个以上点的值(共享此值),那么您应该“绘制”一条线。 (在扫描开始时将有零点,然后是两个(您的第一对),当您找到两个以上的点时,您将能够确定哪个点是第一个多边形,哪个是第二个多边形。

例如,如果你有这些行:

垂直(红色):

x = 0,x = 2,x = 5

水平(黄色):

y = 0,y = 2,y = 3,y = 5

Image with lines and points

你开始扫过X轴,你会得到p1和p2,(我们知道它们属于哪个线方程式)然后你会得到p3,p4,p5和p6 !!所以在这里你可以检查哪些点共享p1和p2的同一行。在这种情况下p4和p5。所以你的第一个新多边形是p1,p2,p4,p5。 现在我们保存“新”点(p3,p6)并继续扫描直到下一个点。这里我们有p7,p8,p9和p10,寻找与先前点(p3和p6)共享线的点,我们得到p7和p10。这些是你的第二个多边形的点。

当我们为Y轴重复练习时,我们将获得两个点(p3,p7),然后只有三个点(p1,p2,p8)!在这种情况下,我们应该在新发现点的同一行中使用最远点(p8)。

由于我们使用线方程和点2或更多维度,程序应该非常相似

ps,对不起我的英文:S

我希望这会有所帮助:)