# hull 折線

``````from scipy.spatial import ConvexHull

# 用 Wire 來建立凸包
def hull2D(points):
hull = ConvexHull(points)
return (cq.Workplane()
.polyline([points[i] for i in hull.vertices])
.close()
.val()
)

# 將 Workplane 中的 Wire 頂點轉為 (x, y)
def toPoints(workplane):
return [(v.X, v.Y) for v in workplane.vertices().vals()]

# 指定折點的 Wire 來建立折線
def polylineJoin2D(points, join):
# 在每個點放上一個 join
joins = [join.translate(p) for p in points]

# 建立點與點間的凸包
lines = [
hull2D(toPoints(joins[i]) + toPoints(joins[i + 1]))
for i in range(len(joins) - 1)
]

# 將全部的凸包擠出，目的是為了利用 `union` 方法來交集
polyline = Workplane(lines[0]).toPending().extrude(1)
for i in range(1, len(lines)):
polyline = polyline.union(Workplane(lines[i]).toPending().extrude(1))

# 取 XY 平面上的 Wire 就可以了
return polyline.faces('<Z').wires().val()

points = [(0, 0), (10, 10), (0, 15), (-10, 10), (-10, 0)]

polyline = polylineJoin2D(points, Workplane().polygon(6, 1))
show_object(polyline)
``````

``````from scipy.spatial import ConvexHull
from cadquery import Vector, Edge, Wire, Solid, Shell, Face, Workplane

# 〈實作 polyhedron〉的 polyhedron 函式
def polyhedron(points, faces):
def _edges(vectors, face_indices):
leng_vertices = len(face_indices)
return (
Edge.makeLine(
vectors[face_indices[i]],
vectors[face_indices[(i + 1) % leng_vertices]]
)
for i in range(leng_vertices)
)

vectors = [Vector(*p) for p in points]

return Solid.makeSolid(
Shell.makeShell(
Face.makeFromWires(
Wire.assembleEdges(
_edges(vectors, face_indices)
)
)
for face_indices in faces
)
)

# 將 Workplane 中的 Solid 頂點轉為 (x, y, z)
def toPoints(workplane):
return [(v.X, v.Y, v.Z) for v in workplane.vertices().vals()]

# 建立 3D 版本的凸包
def hull3D(points):
hull = ConvexHull(points)
# 凸包上的頂點
vertices = [points[i] for i in hull.vertices]

# 用來查詢頂點的索引值
v_i_lookup = {v: i for i, v in enumerate(vertices)}

# 建立面索引
faces = [
[v_i_lookup[points[i]] for i in face]
for face in hull.simplices
]

return polyhedron(vertices, faces)

def polylineJoin3D(points, join):
# 在每個點放上一個 join
joins = [join.translate(p) for p in points]

# 建立點與點間的凸包
lines = [
hull3D(toPoints(joins[i]) + toPoints(joins[i + 1]))
for i in range(len(joins) - 1)
]

# 將全部的凸包交集
polyline = Workplane(lines[0])
for i in range(1, len(lines)):
polyline = polyline.union(Workplane(lines[i]))

return polyline

points = [(0, 0, 0), (10, 0, 0), (10, 0, 10), (10, 10, 10)]
polyline = polylineJoin3D(points, Workplane().box(1, 1, 1))
show_object(polyline)
``````