實體布林操作

November 25, 2021

在 3D 建模軟體中,聯集(Union)、交集(Intersection)、減集(Difference)是最基本的操作,這讓你可以使用一些相對簡單的 3D 實體,來組合出想要的模型。

聯集(Union)

先來看看聯集,在 CadQuery 中,不同 Workplane 實例中管理的 3D 實體,即使視覺上看來重疊在一起,也不會構成聯集,它們位於不同的座標系統,是不同世界的東西。例如:

import cadquery as cq

sphere = cq.Workplane().sphere(10)
box = cq.Workplane().box(20, 20, 1)

雖然在 CQ-editor 中看來如下,不過實際上是兩個模型,並不會自動構成聯集:

實體布林操作

若是用同一個 Workplane 實例來管理 3D 實體,大多數的情況下,新加入的 3D 實體,Workplane 實例會試著與已在管理中的 3D 實體進行聯集。例如:

import cadquery as cq

sphere_box = (cq.Workplane()
				.sphere(10)
				.box(20, 20, 1)
				)

在 CQ-editor 中,雖然視覺上看到的結果還是跟上圖一樣,不過球與方塊會進行聯集;方才談到,大多數的情況下,新加入的 3D 實體,Workplane 實例會試著與已在管理中的 3D 實體進行聯集,會這麼說的原因在於,Workplane 的大多數建立 3D 實體的方法會有 combine 參數,預設值是 True,作用就是將新加入的 3D 實體與管理中的 3D 實體結合,在某些情況下,你會需要將 combine 設為 False,這之後有機會再來談。

減集(Difference)

Workplane 的某些方法會有 cut 參數,大部份會預設為 False,然而有少數會預設為 True,例如 text 方法的 cut 預設就是 True

import cadquery as cq

txt = (cq.Workplane()
			.text('A', 10, 10) # 文字、字型大小、高度
			.text('B', 10, 10)
		)

若方法有 cut 參數且設為 TrueWorkplane 實例會試著與已在管理中的 3D 實體進行聯減集,因此執行以上程式會看到字被挖掉了一部份:

實體布林操作

如果要讓 A 與 B 聯集,方式之一是將 cut 設為 Falsecombine 設為 True(預設是 False):

import cadquery as cq

txt = (cq.Workplane()
			.text('A', 10, 10)
			.text('B', 10, 10, cut = False, combine = True)
		)

執行結果如下:

實體布林操作

另一個方式是,使用 union 方法明確地指定要執行聯集,例如,以下執行結果同上圖:

import cadquery as cq

txt = (cq.Workplane()
			.text('A', 10, 10)
			.union(
				cq.Workplane().text('B', 10, 10)
			)
		)

你可以在〈CadQuery API Reference〉中,找到 API 文件說明,CadQuery 有許多 API,這應該是你會經常查詢的文件。

Workplane 有個 cut 方法,可以明確地指定進行減集:

import cadquery as cq

radius = 10

boxes = (cq.Workplane()
			.box(radius * 2, radius, radius)
			.box(radius, radius * 2, radius)
			.box(radius, radius, radius * 2)
		)

cutted_sphere = (cq.Workplane()
					.sphere(radius)
					.cut(boxes))
	
show_object(cutted_sphere)

在上例中,boxes 是三個立方塊的結合,然後與一個管理了球的 Workplane 進行減集,這邊已經有 CadQuery 的風格了,也就是透過 Workplane 方法鏈操作,表示出一組相關聯的操作構成的 3D 實體,執行之後會看到以下畫面:

實體布林操作

雖然 CadQuery 鼓勵你進行鏈狀操作,不過,不用為了鏈狀操作而鏈狀操作,只要能清楚表達程式碼意圖,適當地運用多個 Workplane,其實是件好事。

交集(Intersection)

若要進行交集,可以透過 intersect 方法,例如:

import cadquery as cq

radius = 10

boxes = (cq.Workplane()
			.box(radius * 2, radius, radius)
			.box(radius, radius * 2, radius)
			.box(radius, radius, radius * 2)
		)

intersected_sphere = (cq.Workplane()
						.sphere(radius)
						.intersect(boxes))
	
show_object(intersected_sphere)

這會產生以下的模型:

實體布林操作

Workplane 定義了 __add____and__ 等運算子方法,union 可以直接透過 +| 來達到,cut 可以直接透過 -intersect 可以直接透過 &,例如:

import cadquery as cq

radius = 10

boxes = (cq.Workplane()
			.box(radius * 2, radius, radius)
			.box(radius, radius * 2, radius)
			.box(radius, radius, radius * 2)
		)

sphere = cq.Workplane().sphere(radius)

cutted_sphere = sphere - boxes
intersected_sphere = (sphere & boxes).translate((radius * 3, 0))

show_object(cutted_sphere)
show_object(intersected_sphere)

這會產生以下的模型:

實體布林操作

對 CadQuery 來說,其實執行 unioncutintersect 算是偏低階的操作,Workplane 基於這些操作封裝了一些更高階的方法,例如在模型上挖洞,就有 holecboreHole 等方法,這之後有機會再來介紹。