【问题标题】:Find minimum number of triangles enclosing all points in the point cloud找到包围点云中所有点的三角形的最小数量
【发布时间】:2019-01-29 00:24:40
【问题描述】:

输入

您有一个表示 2D 点云的点列表。


输出

你必须生成一个三角形列表(应该尽可能少的三角形)所以满足以下限制:

  1. 云中的每个点都应该是三角形的一个顶点,或者是 在三角形内。

  2. 三角形只能建立在点上 原始点云。

  3. 三角形不应与每个三角形相交 其他。
  4. 云的一个点可以是多个三角形的顶点。
  5. 如果三角形顶点位于另一个三角形的边上,我们假设这些三角形不相交。
  6. 如果点位于三角形的边上,我们假设该点在三角形内。

例如


调查

我发明了一种方法来找到给定点集的凸包并将该凸包分成三角形,但这不是正确的解决方案。

你猜怎么解决?

【问题讨论】:

  • 为什么凸包分解成三角形不是正确的解决方案?应该满足您的所有条件
  • @RoryDaulton:这个例子回答了你的问题,不是吗?
  • 显然,凸包的所有顶点都必须是某个三角形的顶点,因此三角形数量的简单下限是 Ceil(H/3)。您的示例表明此下限并不严格。由于船体的大小可以与 N 一样大,因此可能需要 Ceil(N/3) 个三角形。
  • @juvian 凸包的覆盖可能会在中间留下间隙。例如,在插图中,凸包可以通过多种方式仅被 2 个三角形覆盖,但它们都错过了中间点。
  • @juvian 因为在某些情况下,您可以通过较少数量的三角形来覆盖所有点,或者您应该发明正确的分解方法

标签: algorithm math geometry


【解决方案1】:

这是我的看法。

  1. 创建点云的 Delaunay 三角剖分。
  2. 通过半边折叠来简化网格。

对于第 1 步,三角剖分的边界将是凸包。如果您需要遵守非凸边界,也可以使用约束 Delaunay 三角剖分 (CDT)。

对于第 2 步,半边折叠操作将保留现有顶点,因此不会添加新顶点。请注意,在您的情况下,折叠不会删除顶点,它们只会删除边。在应用边缘折叠之前,您应该检查您没有引入三角形反转(产生自相交)并且没有点在三角形之外。塌陷的顺序很重要,但您可以遵循通常的规则,即根据引入劣质三角形(即锐角三角形)来衡量塌陷的“成本”。因此,您应该尽可能选择产生最多等距三角形的折叠。

编辑:

折叠的顺序引导简化到不同的结果。除了最小化锐角之外,它还可以由其他标准指导。我认为最空的三角形可以通过选择产生最多填充的三角形和最空的三角形的折叠来最小化。仍然所有标准都是启发式的。

【讨论】:

  • 为什么你认为应该避免锐角?如果您在给定情况下采用最佳解决方案,并沿某个方向拉伸平面,则最佳三角形将变为锐角。我不确定最优性是否与角度有关。
  • 在几何建模应用程序中,该规则有助于避免“几乎共线”的退化三角形。但你的想法可能是对的。
【解决方案2】:

关于三角形和凸包的一些思考

忽略任何具有 2 个或更少点和 3 个点的集合总是给出 1 个三角形。

  • 制作凸包。
  • 选择任意随机内部点。
    • 除非所有点都在船体中...
  • 外壳中的所有点都必须是三角形的一部分,因为根据凸包的定义,它们不能是内部的。

  • 现在我们有了三角形的上限,即外壳中的点数。

  • 上限也是点数 / 3 四舍五入,因为您可以制作那么多独立的三角形。
  • 所以上限是上述两个中的最小值
  • 我们还可以猜测下限roundup(hull points / 3),因为每3个相邻点可以组成一个三角形,任何多余的点都可以重复使用1-2。

现在是降低上限的困难部分

walk through the inner points using them as center for all triangles.
  If any triangle is empty we can save a triangle by removing the hull edge.
  if two or more adjacent triangles are empty we will have to keep every other triangle or join the 3 points to a new triangle, as the middle point can be left out.
  note the best result.

这位教授是不是没有更好的结果?不。 如果存在一个包围所有剩余点的三角形,那就更好了。

N = number of points
U = upper bound
L = lower bound
T = set of triangles
R = set of remaining points
A = set of all points
B = best solution

BestSolution(A)
  if A < 3 return NoSolution
  if A == 3 return A

  if not Sorted(A) // O(N)
    SortByX(A)     // O(n lg n) or radex if possible O(N)

  H = ConvexHull(A)
  noneHull = A - H
  B = HullTriangles(H, noneHull) // removing empty triangles
  U = size B

  if noneHull == 0
    return U // make triangles of 3 successive points in H and add the remaining to the last 

  if U > Roundup(N/3)
    U = Roundup(N/3)
    B = MakeIndepenTriangles(A)

  AddTriangle(empty, A)

  return // B is best solution, size B is number of triangles.

AddTriangle(T, R)
  if size T+1 >= U return // no reason to test if we just end up with another U solution
  ForEach r in R // O(N)
    ForEach p2 in A-r // O(N)
      ForEach p3 in A-r-p2 // O(N)
        t = Triangle(r, p2, p3)
        c = Candidate(t, T, R)
        if c < 0 
          return c+1 // found better solution
  return 0

Candidate(t, T, R)
  if not Overlap(t, T) // pt. 3, O(T), T < U
    left = R-t
    left -= ContainedPoints(t) // O(R) -> O(N)

    if left is empty
      u = U
      U = size T + 1
      B = T+t
      return U-u // found better solution

    return AddTriangle(T+t, left)
  return 0

所以……总运行时间……

候选人 O(N) 加三角形 O(N^3) 递归仅限于当前最优解 U

O((N N^3)^U) -> O((N^4)^U) 空间是 O(U N)

因此,在我们使用蛮力之前减少 U 是必不可少的。 - 快速减少 R 应该减少递归 - 所以从更大的并且希望更多的封闭三角形开始会很好 - 船体中的任何 3 点都应该是一些不错的候选者 - 这些将剩余的点分成 3 个部分,可以独立调查 - 将每个部分视为一个外壳,其中它的 2 个基点是三角形的一部分,但第 3 个基点不在集合中。 - 如果可能,将其设为 BFS,以便我们首先选择最封闭的 - 空间可能是个问题 - O(HUN) - 否则首先从船体周围 1/3 的点开始。

AddTriangle 真的很糟糕,所以我们真的可以制作多少个三角形

从 N 中选择 3 是

N!/(N-3)!

而且我们不关心订单所以

N!/(3!(N-3)!)
N!/(6(N-3)!)
N (N-1) (n-2) / 6

对于循环来说仍然是 O(N^3),但它让我们感觉更好。如果排列时间过长,循环可能仍然更快。

AddTriangle(T, R)
  if size T+1 >= U return // no reason to test if we just end up with another U solution
  while t = LazySelectUnordered(3, R, A) // always select one from R first O(R (N-1)(N-2) / 6) aka O(N^3)
    c = Candidate(t, T, R)
    if c < 0 
      return c+1 // found better solution
  return 0

【讨论】:

    猜你喜欢
    • 2015-11-21
    • 2019-03-31
    • 2011-10-09
    • 2013-09-22
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    • 2010-12-03
    • 2018-04-08
    相关资源
    最近更新 更多