两个剖面的交点

时间:2012-10-09 14:51:31

标签: geometry computational-geometry csg

我正在尝试使用两个(或更多)剖面来查找切割3D对象的算法。只应切割两个截面均为切割的对象。因此,请考虑以下与两个剖面相交的abcd矩形:s0和s1; s1向右切,s0向右切。我想要的是产生ajikcd形状。

.        |s1
. a______j_________b  ^
. |      |         |  |
. |- - - i - - - - |k- - s0
. |      |         |  
. d----------------c
.        |->

这是一个非常简单的例子,但我希望它能说明我想要完成的事情。此外,这应该在3D中完成。

有没有人知道任何这样做的库,还是算法呢?这似乎是一个非常微不足道的问题,有人必须在我之前解决! :)

我必须补充一点,我知道如何做基础(平面与面/平面/边缘的交点)。我无法看到的是,是否有一种聪明的方法来解决所有可能的情况(在这一个中,必须添加两个面,但在其他一些面上可能只创建一个面,等等),或者如果你应该处理它们分开。

我应该添加的另一件事是我不关心渲染部分,我知道如何使用剪切平面的OpenGL来完成它。我想要的是能够计算对象的新拓扑。

1 个答案:

答案 0 :(得分:0)

我认为通过将对象切片,移除不需要的部分,然后通过合并面部将剩余的部分粘合在一起,可以很容易地解决这个问题。

假设您正在将对象建模为完全链接的图形

  • 顶点列表,每个顶点都有一个边列表
  • 边缘列表,每个边缘都引用了两个顶点和两个面
  • 面部列表,每个面部都有边缘列表

只要您小心维护和操作此图表,它就会包含快速剪切和合并对象所需的所有信息。

您可以使用this answer中描述的算法来计算剪切产生的新面孔。

所以:你对算法的输入是一个切割平面列表和一个对象列表 - 最初只有一个。 对于每个切割平面,将列表对象中的每个对象切成两个并将它们放回列表中。 添加的两个面(每个新对象上一个)应该保持对生成它们的切割平面的引用。 对于由平面切成两半的面,请记住生成的两个新面应该继承此引用(如果存在)。 新对象应该记录它们所在平面的哪一侧(只是一个布尔意思是“保持”或“丢弃”) - 这些记录也应该在对象进一步细分时保持。

一旦完成所有切割,您将拥有一个对象列表,每个对象都有一个记录列表,详细说明它们所在的切割平面的哪一侧。 找到所有这些记录都被“丢弃”的对象并扔掉它们。

我们现在必须将这些物品重新组合在一起。

从简单地合并对象图开始 - 简单地将所有顶点,边和面列表组合到一个对象中。我们现在检查由同一切割平面创建的两个面:

  • 如果两个面相同(即:它们共享同一组顶点),则可以移除两个面和所有相关边。
  • 如果一个面的顶点集大于另一个面,则删除较小的面和所有共享边。

您现在应该有一个合并对象,但有一些无关的顶点。简单地遍历顶点并删除那些只有两个相关边的顶点。

以下是切割如何工作的示例:

      :
a---1-:---b
|     :   |
2   X :   3
|     :   |
|     :   |
c---4-:---d
      :
      :s 

我们从一个对象开始(?表示某些边或面未显示):

verts:
  a:1,2,?
  b:1,3,?
  c:2,4,?
  d:3,4,?
edges:
  1:a,b X,?
  2:a,c X,?
  3:b,d X,?
  4:c,d X,?
faces:
  X:1,2,3,4
  ?:...

当我们用平面切割时,我们最终得到两个物体:

a--1--e-7-b
|     |   |
2  X  5 Y 3
|     6   |
|     |   |
c--4--f-8-d

verts:            verts:         
  a:1,2,?           e:1,5,6,7    
  e:1,5,6,7         b:3,7,?        
  c:2,4,?           d:3,8,?        
  f:4,5,6,8         f:4,5,6,8    
edges:            edges:         
  1:a,e X,?         3:b,d Y,?    
  2:a,c X,?         6:e,f Y,W    
  4:c,f X,?         7:e,b Y,?    
  5:e,f X,V         8:f,d Y,?    
faces:            faces:         
  X:1,2,3,4         Y:3,6,7,8    
  V:5,...           W:6,...      
  ?:...             ?:...

我们添加了顶点e和f,边5和6以及面V和W.请注意,边5和6是不同的对象,在不同的面之间共享相同的顶点。

当我们将这两个对象合并在一起时,我们首先简单地合并两个对象图:

verts:
  a:1,2,?
  b:3,7,?        
  c:2,4,?
  d:3,8,?
  e:1,5,6,7        
  f:4,5,6,8  
edges:
  1:a,e X,?         
  2:a,c X,?         
  3:b,d Y,?    
  4:c,f X,?         
  5:e,f X,V         
  6:e,f Y,W    
  7:e,b Y,?
  8:f,d Y,?    
faces:
  X:1,2,3,4
  Y:3,6,7,8    
  V:5,...           
  W:6,...      
  ?:...

我们可以看到,面V和W是由相同的切割平面生成的,并且具有相同的顶点集,因此可以将它们与相关边一起移除。合并与一对重合边相关联的两个未移除的面。

a--1--e-7-b
|         |
2  X      3
|         |
|         |
c--4--f-8-d

verts:
  a:1,2,?
  b:3,7,?        
  c:2,4,?
  d:3,8,?
  e:1,7        
  f:4,8  
edges:
  1:a,e X,?         
  2:a,c X,?         
  3:b,d X,?    
  4:c,f X,?    
  7:e,b X,?
  8:f,d X,?    
faces:
  X:1,2,3,4,7,8
  ?:...

然后我们可以只删除两个相关边的顶点,然后合并这些边:

verts:
  a:1,2,?
  b:1,3,?        
  c:2,4,?
  d:3,8,?
edges:
  1:a,e X,?         
  2:a,c X,?         
  3:b,d Y,?    
  4:c,d X,?
faces:
  X:1,2,3,4
  Y:3,6,7,8  
  ?:...

合并这些对象怎么样?

a--1--e
|     5   
2  X  g-3-b
|     6   |
|     9 Y 7
c--4--f-8-d

verts:            verts:         
  a:1,2,?           g:3,5,6,?    
  e:1,5,?           b:3,7,?        
  c:2,4,?           d:7,8,?        
  f:4,6,8,9,?       f:4,6,8,9,?
edges:            edges:         
  1:a,e X,?         3:b,g Y,?    
  2:a,c X,?         9:f,g Y,W    
  4:c,f X,?         7:b,d Y,?    
  5:e,g X,V,?       8:f,d Y,?    
  6:f,g X,V
faces:            faces:         
  X:1,2,4,5,6       Y:3,7,8,9
  V:5,6,...         W:9,...      
  ?:...             ?:...

我们合并:

verts:
  a:1,2,?    
  b:3,7,?               
  e:1,5,?           
  c:2,4,?           
  d:7,8,?        
  f:4,6,8,9,?         
  g:3,5,6,9,?    
edges:
  1:a,e X,?         
  2:a,c X,?         
  3:b,g Y,?    
  4:c,f X,?         
  5:e,g X,V,?         
  6:f,g X,V
  7:b,d Y,?    
  8:f,d Y,?    
  9:f,g Y,W    
faces:
  X:1,2,4,5,6
  Y:3,6,7,8    
  V:5,6,...
  W:9,...
  ?:...

并检查面V和W,因为它们是由同一切割平面创建的。这次他们的顶点集是不同的。取下较小的脸。在这两个面中,找到具有相同顶点的边并将其移除:

a--1--e
|     5   
2  X  g-3-b
|         |
|         7
c--4--f-8-d

verts:
  a:1,2,?    
  b:3,7,?               
  e:1,5,?           
  c:2,4,?           
  d:7,8,?        
  f:4,8         
  g:3,5,?    
edges:
  1:a,e X,?         
  2:a,c X,?         
  3:b,g X,?    
  4:c,f X,?         
  5:e,g X,V,?
  7:b,d X,?    
  8:f,d X,?
faces:
  X:1,2,3,4,5,7,8
  V:5,...
  ?:...

现在我们可以删除只有两个入射边的无用顶点:

a--1--e
|     5   
2  X  g-3-b
|         |
|         7
c----4----d

verts:
  a:1,2,?    
  b:3,7,?               
  e:1,5,?           
  c:2,4,?           
  d:4,7,?   
  g:3,5,?    
edges:
  1:a,e X,?         
  2:a,c X,?         
  3:b,g Y,?    
  4:c,d X,?         
  5:e,g X,?
  7:b,d X,?
faces:
  X:1,2,3,4,5,7
  V:5,...
  ?:...

唷!希望这会有所帮助...