# Face 布林操作

CadQuery 採 BREP 概念，從頂點到複合體，它們都是 `Shape` 的子型態，而 `Shape` 定義了 `intersect``cut``fuse` 方法，也就是說，從頂點到複合體，都可以進行布林操作。

``````from cadquery import Vector, Wire, Face

# 建立 Wire
normal = Vector(0, 0, 1) # 用法向量指定平面
wire_c1 = Wire.makeCircle(5, Vector(0, 0, 0), normal)
wire_c2 = Wire.makeCircle(5, Vector(5, 0, 0), normal)

# 建立 Face
face_c1 = Face.makeFromWires(wire_c1)
face_c2 = Face.makeFromWires(wire_c2)

# 用 Face 來交集
intersected = face_c1.intersect(face_c2)

show_object(intersected)
``````

`intersected` 參考的會是 `Compound` 實例，可以透過 `Vertices``Edges``Wires` 等方法，取得對應型態的物件，例如，若想進行擠出必須如下：

``````from cadquery import Vector, Wire, Face, Solid

normal = Vector(0, 0, 1) # 用法向量指定平面
wire_c1 = Wire.makeCircle(5, Vector(0, 0, 0), normal)
wire_c2 = Wire.makeCircle(5, Vector(5, 0, 0), normal)

# 建立 Face
face_c1 = Face.makeFromWires(wire_c1)
face_c2 = Face.makeFromWires(wire_c2)

# 用 Face 來交集
intersected = face_c1.intersect(face_c2)
wires = intersected.Wires() # 傳回一組 Wire

solid = Solid.extrudeLinear(wires[0], [], Vector(0, 0, 10))
show_object(solid)
``````

`Wires` 方法名稱是複數，這是因為某些 `Face` 交集後，可能會產生兩個以上分離的 `Face`，從分離的 `Face` 自然會取得分離的 `Wire`；另一方面，面可能是空心也是一個原因，稍後會談到。

``````from cadquery import Vector, Wire, Face, Solid

normal = Vector(0, 0, 1) # 用法向量指定平面
wire_c1 = Wire.makeCircle(5, Vector(0, 0, 0), normal)
wire_c2 = Wire.makeCircle(5, Vector(5, 0, 0), normal)

# 建立 Face
face_c1 = Face.makeFromWires(wire_c1)
face_c2 = Face.makeFromWires(wire_c2)

# 用 Face 來減集
intersected = face_c1.cut(face_c2)
wires = intersected.Wires()

solid = Solid.extrudeLinear(wires[0], [], Vector(0, 0, 10))
show_object(solid)
``````

``````from cadquery import Vector, Wire, Face

normal = Vector(0, 0, 1) # 用法向量指定平面
wire_c1 = Wire.makeCircle(5, Vector(0, 0, 0), normal)
wire_c2 = Wire.makeCircle(5, Vector(5, 0, 0), normal)

# 建立 Face
face_c1 = Face.makeFromWires(wire_c1)
face_c2 = Face.makeFromWires(wire_c2)

# 用 Face 來融合
intersected = face_c1.fuse(face_c2)
wires = intersected.Wires()

for wire in wires:
show_object(wire)
``````

``````from cadquery import Vector, Wire, Face

normal = Vector(0, 0, 1) # 用法向量指定平面
wire_c1 = Wire.makeCircle(5, Vector(0, 0, 0), normal)
wire_c2 = Wire.makeCircle(5, Vector(5, 0, 0), normal)

# 建立 Face
face_c1 = Face.makeFromWires(wire_c1)
face_c2 = Face.makeFromWires(wire_c2)

# 用 Face 來並集
intersected = face_c1.fuse(face_c2).clean()
wires = intersected.Wires()

show_object(wires)
``````

``````from cadquery import Vector, Wire, Face

normal = Vector(0, 0, 1) # 用法向量指定平面
outerWire = Wire.makeCircle(10, Vector(0, 0, 0), normal)
innerWire1 = Wire.makeCircle(2, Vector(5, 0, 0), normal)
innerWire2 = Wire.makeCircle(2, Vector(-5, 0, 0), normal)

face = Face.makeFromWires(outerWire, [innerWire1, innerWire2])
show_object(face)
``````

``````from cadquery import Vector, Wire, Face, Solid

normal = Vector(0, 0, 1) # 用法向量指定平面

# 空心圓
face_circle = Face.makeFromWires(
Wire.makeCircle(10, Vector(0, 0, 0), normal),
[Wire.makeCircle(5, Vector(0, 0, 0), normal)]
)

# 有兩個空心的橢圓
face_ellipse = Face.makeFromWires(
Wire.makeEllipse(15, 3, Vector(0, 0, 0), normal, Vector(1, 0, 0)),
[
Wire.makeCircle(1, Vector(8, 0, 0), normal),
Wire.makeCircle(1, Vector(-8, 0, 0), normal)
]
)

intersected = face_circle.intersect(face_ellipse)
height = Vector(0, 0, 10)
# 逐一取得面
for face in intersected.Faces():
solid = Solid.extrudeLinear(
face.outerWire(),
face.innerWires(),
height
)
show_object(solid)
``````

``````from cadquery import Vector, Edge, Wire, Face, Compound

# 實作 circle、square
def circle(radius, center = None):
ct = Vector(*center) if center else Vector(0, 0)
return Compound.makeCompound([
Face.makeFromWires(
Wire.makeCircle(radius, ct, Vector(0, 0, 1))
)
])

def square(size, center = None):
ct = center if center else [0, 0]
x = size[0] / 2
y = size[1] / 2
edges = [
Edge.makeLine(Vector(ct[0] + x, ct[1] - y), Vector(ct[0] + x, ct[1] + y)),
Edge.makeLine(Vector(ct[0] + x, ct[1] + y), Vector(ct[0] - x, ct[1] + y)),
Edge.makeLine(Vector(ct[0] - x, ct[1] + y), Vector(ct[0] - x, ct[1] - y)),
Edge.makeLine(Vector(ct[0] - x, ct[1] - y), Vector(ct[0] + x, ct[1] - y))
]
return Compound.makeCompound([
Face.makeFromWires(
Wire.assembleEdges(edges)
)
])

show_object(circle(5))
show_object(square([5, 5], center = [5, 5]))
``````

`circle``square` 傳回的是 `Compound`，這是為了統一使用的型態，接著以實作 `difference` 為例，接受的是 `Compound`，傳回的是 `Compound`

``````from cadquery import Vector, Edge, Wire, Face, Compound, Workplane

def circle(radius, center = None):
ct = Vector(*center) if center else Vector(0, 0)
return Compound.makeCompound([
Face.makeFromWires(
Wire.makeCircle(radius, ct, Vector(0, 0, 1))
)
])

def square(size, center = None):
ct = center if center else [0, 0]
x = size[0] / 2
y = size[1] / 2
edges = [
Edge.makeLine(Vector(ct[0] + x, ct[1] - y), Vector(ct[0] + x, ct[1] + y)),
Edge.makeLine(Vector(ct[0] + x, ct[1] + y), Vector(ct[0] - x, ct[1] + y)),
Edge.makeLine(Vector(ct[0] - x, ct[1] + y), Vector(ct[0] - x, ct[1] - y)),
Edge.makeLine(Vector(ct[0] - x, ct[1] - y), Vector(ct[0] + x, ct[1] - y))
]
return Compound.makeCompound([
Face.makeFromWires(
Wire.assembleEdges(edges)
)
])

# 實作交集、減集、聯集
def intersection(compound1, compound2):
return compound1.intersect(compound2)

def difference(compound1, compound2):
return compound1.cut(compound2)

def union(compound1, compound2):
return compound1.fuse(compound2).clean()

c = circle(5)
s = square([5, 5], center = [5, 5])

show_object(intersection(c, s))
show_object(Workplane(difference(c, s)).translate((10, 0)))
show_object(Workplane(union(c, s)).translate((20, 0)))
``````

``````from cadquery import Vector, Edge, Wire, Face, Compound, Solid, Workplane

def circle(radius, center = None):
ct = Vector(*center) if center else Vector(0, 0)
return Compound.makeCompound([
Face.makeFromWires(
Wire.makeCircle(radius, ct, Vector(0, 0, 1))
)
])

def square(size, center = None):
ct = center if center else [0, 0]
x = size[0] / 2
y = size[1] / 2
edges = [
Edge.makeLine(Vector(ct[0] + x, ct[1] - y), Vector(ct[0] + x, ct[1] + y)),
Edge.makeLine(Vector(ct[0] + x, ct[1] + y), Vector(ct[0] - x, ct[1] + y)),
Edge.makeLine(Vector(ct[0] - x, ct[1] + y), Vector(ct[0] - x, ct[1] - y)),
Edge.makeLine(Vector(ct[0] - x, ct[1] - y), Vector(ct[0] + x, ct[1] - y))
]
return Compound.makeCompound([
Face.makeFromWires(
Wire.assembleEdges(edges)
)
])

def intersection(compound1, compound2):
return compound1.intersect(compound2)

def difference(compound1, compound2):
return compound1.cut(compound2)

def union(compound1, compound2):
return compound1.fuse(compound2).clean()

# 實作 linear_extrude
def linear_extrude(compound, height):
solids = []
for face in compound.Faces():
solids.append(
Solid.extrudeLinear(
face.outerWire(),
face.innerWires(),
Vector(0, 0, height)
)
)
return Compound.makeCompound(solids)

c = circle(5)
s = square([5, 5], center = [5, 5])

intersected = intersection(c, s)
differenced = difference(c, s)
unioned = union(c, s)

show_object(linear_extrude(intersected, 4))
show_object(Workplane(linear_extrude(differenced, 2)).translate((10, 0)))
show_object(Workplane(linear_extrude(unioned, 1)).translate((20, 0)))
``````