查找包围点云中所有点的最小三角形数

时间:2018-08-22 17:10:51

标签: algorithm math geometry

输入

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


输出

您必须生成三角形的列表(应尽可能减少三角形),以便满足以下限制:

  1. 来自云的每个点应为三角形的顶点或为 三角形内。

  2. 只能在以下点上构建三角形 原始点云。

  3. 三角形不应该彼此相交 其他。
  4. 云的一个点可以是多个三角形的顶点。
  5. 如果三角形顶点位于另一个三角形的侧面,则假定这些三角形不相交。
  6. 如果点位于三角形的侧面,则假定该点位于三角形内部。

例如

Original point cloud and enclosing triangles


调查

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

有人猜测如何解决吗?

2 个答案:

答案 0 :(得分:0)

这是我的意见。

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

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

对于步骤2,半边折叠操作将保留现有顶点,因此将不添加任何新顶点。请注意,在您的情况下,塌陷并没有去除顶点,而是仅去除了边缘。在应用边缘折叠之前,应检查是否未引入三角形倒置(会产生自相交),并且没有点在三角形之外。坍塌的顺序很重要,但是您可以遵循通常的规则,即通过引入质量较差的三角形(即具有锐角的三角形)来衡量崩溃的“成本”。因此,您应该选择能够产生最多等距三角形的折叠。

编辑:

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

答案 1 :(得分:0)

关于三角形和凸包的一些困惑

忽略任何包含2个或更少点和3个点的集合,总会得到1个三角形。

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

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

  • 上限也是点数/ 3的舍入,因为您可以制作许多独立的三角形。
  • 所以上限是上述两个中的最小值
  • 我们还可以猜测下限取整(船体点/ 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) AddTriangle O(N ^ 3) 递归仅限于当前的最佳解决方案U

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

因此在使用蛮力之前降低U值至关重要。 -快速降低R应该减少递归   -因此,从更大且希望更多的封闭三角形开始会很好     -船体中的任何3分都应成为不错的候选者       -这些将剩余的点分为3部分,可以分别进行调查         -将每个零件视为船体,其中其2个基点是三角形的一部分,而第三个基点不在集合中。       -如果可能的话,使其成为BFS,以便我们选择最封闭的         -空间迁移是一个问题           -O(H U N)       -否则首先要从相对于船壳的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