3D 布尔操作

语法

  • union B-Rule
  • union(swapMode) B-Rule
  • subtract B-Rule
  • subtract(swapMode) B-Rule
  • intersect B-Rule
  • intersect(swapMode) B-Rule

参数

  1. swapMode - selector
    • noSwap - 默认。 运算对象 A(当前形状)为目标。
    • swap - 运算对象 B (B-Rule) 为目标。
  2. B-Rule
    使用内联派生定义运算对象 B 的规则或一系列操作:
    • identifier - 规则的名称。
    • { operations } - 花括号中的一系列形状操作。

描述

unionintersectsubtract 操作在当前形状(运算对象 A)和内联 B-Rule(运算对象 B)的结果之间执行指定 3D 布尔操作。 swapMode 参数用于确定目标形状,例如,可以从运算对象 B 中减去运算对象 A。 该参数还可以确定最终的形状属性并指定用于叠加几何的材料。 构造运算对象 B 类似于使用 inline(unify) B-Rule,这意味着将首先使用 union 操作合并由 B-Rule 推导得到的形状。

如果运算对象具有冲突的材料属性,则首先将其材料写入几何,由此确保保留所有材料属性。

注:
该操作可以处理 3D 和 2D 输入。 当所有输入折点均位于同一平面时,将执行 2D 布尔操作。

注:

一般来说,仅针对封闭的密封网格定义 3D 布尔操作,因为结果由相交段周围的局部内部/外部测试确定。 当使用开放运算对象时,结果将取决于相交发生的位置 - 参见示例

组件标签

操作自动将语义组件标签应用于生成的面组件:

union、subract 和 intersect 组件标签

"bool.A" 蓝色:来自运算对象 A 的面。

"bool.B" 绿色:来自运算对象 B 的面。

Left   --> extrude(1) 
           union Sphere
           comp(f) { isTagged("bool.A"): Blue 
                   | isTagged("bool.B"): Green }
Sphere --> t(0.3, 0.3, 0.3) primitiveSphere()

Middle --> ... subtract Sphere ...
Right  --> ... intersect Sphere ...

注:
"bool.A""bool.B" 均应用于叠加面(2D 情况)。

有关使用组件标签的详细信息,请参阅:

相关内容

示例

交换模式

Left -->
    color("#0399F5") // blue
    primitiveCube
    subtract Cylinder
    
Right --> 
    color("#0399F5") // blue
    primitiveCube
    subtract(swap) Cylinder
 
Cylinder -->
    color("#09DE1F") // green
    t(3,3,3)
    primitiveCylinder

swapMode 参数用于确定将从另一个形状中减去哪个形状。

布尔交换模式减去
Left -->
    color("#0399F5") // blue
    union Circle
    
Right --> 
    color("#0399F5") // blue
    union(swap) Circle
 
Circle -->
    color("#09DE1F") // green
    t(3,0,3)
    primitiveDisk

swapMode 参数用于确定叠加面的材料。

布尔交换模式材料
attr Height = 10

Left -->
    intersect Circle
    extrude(Height) // Height == 10
    
Right --> 
    intersect(swap) Circle
    extrude(Height) // Height == 1
 
Circle -->
    set(Height, 1)
    t(3,0,3)
    primitiveDisk

swapMode 参数用于确定生成形状的属性。

布尔交换模式属性

B-Rule

Left -->
    color("#0399F5") // blue
    primitiveCube
    union {
        color("#09DE1F") // green
        t(1,1,1) B.
    }
    
Right --> 
    color("#0399F5") // blue
    primitiveCube
    union {
        color("#09DE1F") // green
        t(1,1,1) B0.
        t(1,1,1) B1.
        t(1,1,1) B2.
    }

运算对象 B 由 B-Rule 确定,由此产生单个形状(左)或多个形状(右)。 如果存在多个形状,则首先将其合并,类似于使用 inline(unify)

B-rule 单个形状或多个形状
Init -->
    color("#0399F5") // blue
    primitiveCube
    union {
        color("#09DE1F") // green
        t(1,1,11) B0.
        t(1,1,1) B1.
        t(1,1,1) B2.
    }

如果 B-Rule 产生多个形状,即使它们未与运算对象 A 相交,它们也是统一的。

B-rule 单个形状或多个形状未接触

体量建模

Init -->
    extrude(45)
    intersect Sphere

Sphere --> 
    s('1, '1, '2)
    center(z)
    t(0, '-0.2, 0)
    primitiveSphere

步骤 1:已拉伸的初始形状(当前形状,作为运算对象 A)与插入的球体(规则 Sphere 的结果,作为运算对象 B)相交。

布尔半球相交
Init -->
    extrude(40)
    intersect Sphere
    inline(unify) split(y) { ~1: LowerHalf
                           | 20: UpperHalf }

LowerHalf --> X.
UpperHalf --> t(10,0,0) r(scopeCenter,0,7.2,0)

步骤 2:将当前形状分割成两部分。 如果使用 inline(unify),则生成的形状统一(注意消失的内表面)。

我们将使用 inline(unify) 操作,而非 union 操作,因为我们不希望向当前形状添加几何,而是将其替换为分割操作所生成形状的并集(即 LowerHalfUpperHalf)。

布尔半球统一
Init -->
    extrude(40)
    intersect Sphere
    inline(unify) split(y) { ~1: LowerHalf
                           | 20: UpperHalf }
    subtract Hole
    
Hole -->
    s(16, 16, '1.2)
    center(z)
    t(30, 5, 0)
    rotateScope(-90, 0, 0)
    primitiveCylinder

步骤 3:我们将通过减去一个圆柱体(规则 Hole 的结果,用作运算对象 B)来继续细化体量(步骤 1 和 2 后的当前形状,作为运算对象 A)。

布尔半球减去
Init -->
    extrude(40)
    tag("Envelope")
    intersect Sphere
    inline(unify) split(y) { ~1: LowerHalf
                           | 20: UpperHalf }
    subtract Hole
    comp(f) { isTagged("Envelope") && side: Blue
            | isTagged("Lower") && top    : Red
            | isTagged("Upper") && bottom : Orange
            | isTagged("Lower")           : Green
            | isTagged("Upper")           : Yellow
            | isTagged("Hole")            : Purple }

Sphere --> 
    s('1, '1, '2)
    center(z)
    t(0, '-0.2, 0)
    primitiveSphere

LowerHalf --> tag("Lower")
UpperHalf --> 
    t(10,0,0) 
    r(scopeCenter,0,7.2,0)
    tag("Upper")
              
Hole --> 
    s(16, 16, '1.2)
    center(z)
    t(30, 5, 0)
    rotateScope(-90, 0, 0)
    primitiveCylinder
    tag("Hole")

Blue -->   color("#0399F5")
Green -->  color("#09DE1F")
Yellow --> color("#FADB19")
Purple --> color("#8D09DE")
Red -->    color("#FF360A")
Orange --> color("#FA9100")

添加标签:使用 3D 布尔操作,可以轻松创建具有复杂表面的体量模型。 在本示例中,在每个步骤中添加了标签,由此可在最后为不同的表面分配正确的规则(此处使用不同的颜色表示)。

布尔半球 3 个标签

3D 布尔和自动标签

Init --> 
    extrude(40)
    subtract {
        t(20,-15,-15)
        rotate(rel,scope,15,12,25)	
    }
    SurfaceSplitter

SurfaceSplitter -->
    comp(f) { isTagged("extrude.top") 
                  && isTagged("bool.A"): Purple
            | isTagged("extrude.top") 
                  && isTagged("bool.B"): Green
            | isTagged("extrude.side")
                  && isTagged("bool.A"): Blue
            | isTagged("extrude.side") 
                  && isTagged("bool.B"): Yellow }

在本示例中,首先拉伸初始形状,由此可向所有面添加“extrude自动标签。 然后,减去形状的平移和旋转副本,由此可向生成的面额外添加“bool”自动标签。 最后,这些标签用于提取不同的表面并对其进行相应着色。

3D 布尔和自动标签

布局建模

Init -->
    primitiveDisk(5)
    union FrontyardFootprint
    ShowBoolAutotags
    
FrontyardFootprint -->
    s(10,0,10)
    center(x)
    t(0,0,'-0.33)
    
ShowBoolAutotags -->
    comp(f) { isTagged("bool.A")
                  && isTagged("bool.B"): Yellow
            | isTagged("bool.A")       : Blue
            | isTagged("bool.B")       : Green }

步骤1:插入五边形 (primitiveDisk(5)),然后用缩小的副本执行 union 操作。 union 操作将保留所有原始边,这意味着生成的几何包含 3 个面,如颜色所示。

布局建模 0
Init -->
    primitiveDisk(5)
    union FrontyardFootprint
    deleteUV(0)
    inline(append) comp(f) { isTagged("bool.B")= B
                           | isTagged("bool.A")= A }
    cleanupGeometry(vertices, 0) // reconnect faces
    ShowTags
   
A --> tag("eHouse", edges)
B --> deleteTags("bool.A")
      cleanupGeometry(edges, 0) // merge faces
      tag("eFrontyard", edges)
      
ShowTags -->
    ShowBoolAutotags
    comp(e) { isTagged("eFrontyard") 
                  && isTagged("eHouse"): YellowEdge
           | isTagged("eHouse")        : BlueEdge
           | isTagged("eFrontyard")    : GreenEdge }

步骤 2:目标是合并黄色和绿色的面并标记边,为步骤 3 做好准备。 comp 用于修改相应的面,inliningcleanupGeometry 用于将修改后的部分重新合并在一起。

注:
为了使用 cleanupGeometry 合并规则 B 中的面,需要使用 deleteUV 移除已插入资产上的 UV 坐标,然后需要使用 deleteTags 移除“bool.A”,否则会阻止该过程。

布局建模 1
Init -->
    primitiveDisk(5)
    union FrontyardFootprint
    deleteUV(0)
    inline(append) comp(f) { isTagged("bool.B")= B
                           | isTagged("bool.A")= A }
    cleanupGeometry(vertices, 0) // reconnect faces
    comp(f) { isTagged("bool.A"): House
            | isTagged("bool.B"): Frontyard }
            
House -->
    extrude(3)
    comp(f) { isTagged("eFrontyard"): Yellow
            | all                   : Blue }

Frontyard -->
    offset(-1)
    comp(f) { isTagged("eHouse"): Yellow
            | all               : Green }

步骤 3:对房屋覆盖区进行拉伸,并对前院覆盖区进行偏移。 步骤 2 中的边标签将自动传播到新面,由此可区分面向前院的立面以及与房屋接触的偏移边界。

此信息可用于在后续步骤中对入口区域进行建模。

布局建模 2

开放运算对象的行为

Left -->
    color("#0399F5") // blue
    primitiveCube
    union {
        color("#09DE1F") // green
        t(2,2,2) 
        comp(f) { front: NIL | all= B. }
    }
    
Right --> 
    color("#0399F5") // blue
    primitiveCube
    union {
        color("#09DE1F") // green
        t(2,2,2) 
        comp(f) { left: NIL | all= B. }
    }

运算对象 A 为封闭立方体,而运算对象 B 为开放立方体。 左:B 的开放边界不是相交的运算对象 A。 右:B 的开放边界是相交的运算对象 A。

布尔封闭立方体和开放立方体
Left -->
    color("#0399F5") // blue
    primitiveCube
    union {
        color("#09DE1F") // green
        primitiveQuad
        s(12,0,12)
        center(xyz)
    }
    
Right -->
    color("#0399F5") // blue
    primitiveCube
    union {
        color("#09DE1F") // green
        primitiveQuad
        s(12,0,10)
        t(-1,5,2)
    }

运算对象 A 为封闭立方体,而运算对象 B 为 2D 四边形。 左:四边形完全切割立方体。 平面以下的所有部分均视为“内部”,因此将会消失。 右:四边形部分切割立方体。

布尔封闭立方体和开放立方体