# 建立網格面

``````points = []
for y in range(min_value, max_value, step):
row = []
for x in range(min_value, max_value, step)
row.append([x, y, f(x, y)])
points.append(row)
``````

``````from cadquery import Vector, Vertex, Edge, Wire, Solid, Shell, Face

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
)
)

def surface(points, thickness):
leng_row = len(points)
leng_col = len(points[0])
leng_pts = leng_col * leng_row

def _all_pts():
half_thickness = thickness / 2

# 轉為向量
vectors = [[Vector(*p) for p in row] for row in points]

# 用於查詢指定位置的法向量
# makeSplineApprox 的控制點以每行（column）為一組
# 因此需要將 points 轉置
face = Face.makeSplineApprox([[
Vector(*points[ri][ci])
for ri in range(leng_row)
] for ci in range(leng_col)]
)

front_thicken_pts = [] # 正面的點
back_thicken_pts = []  # 背面的點
for row in vectors:
for vt in row:
# 頂點處的單位法向量
n = face.normalAt(vt).normalized()
# 計算正面的點並收集
v = vt + n.multiply(half_thickness)
front_thicken_pts.append([v.x, v.y, v.z])
# 計算背面的點並收集
v = vt + n.multiply(-half_thickness)
back_thicken_pts.append([v.x, v.y, v.z])
return front_thicken_pts + back_thicken_pts

def _all_faces():
# 正面索引
front_faces = []
for ri in range(leng_row - 1):
for ci in range(leng_col - 1):
front_faces.append([ci + leng_col * ri, (ci + 1) + leng_col * ri, (ci + 1) + leng_col * (ri + 1)])
front_faces.append([ci + leng_col * ri, (ci + 1) + leng_col * (ri + 1), ci + leng_col * (ri + 1)])

# 背面索引
back_faces = [[f[2] + leng_pts, f[1] + leng_pts, f[0] + leng_pts] for f in front_faces]

# 四個邊的索引
side_faces1 = []
for ci in range(leng_col - 1):
side_faces1.append([ci, ci + leng_pts, ci + 1])
side_faces1.append([ci + leng_pts, ci + leng_pts + 1, ci + 1])

side_faces2 = []
rx = leng_col - 1
for ri in range(leng_row - 1):
side_faces2.append([rx + (ri + 1) * leng_col + leng_pts, rx + (ri + 1) * leng_col, rx + ri * leng_col])
side_faces2.append([rx + ri * leng_row + leng_pts, rx + (ri + 1) * leng_col + leng_pts, rx + ri * leng_col])

side_faces3 = []
for ci in range(leng_pts - leng_col, leng_pts - 1):
side_faces3.append([ci + 1, ci + leng_pts, ci])
side_faces3.append([ci + 1, ci + leng_pts + 1, ci + leng_pts])

side_faces4 = []
for ri in range(leng_row - 1):
side_faces4.append([ri * leng_col, (ri + 1) * leng_col, (ri + 1) * leng_col + leng_pts])
side_faces4.append([ri * leng_col, (ri + 1) * leng_col + leng_pts, ri * leng_row + leng_pts])

return front_faces + back_faces + side_faces1 + side_faces2 + side_faces3 + side_faces4

return polyhedron(_all_pts(), _all_faces())
``````

``````# 要結合以上的 polyhedron 及 surface

def paraboloid(x, y):
return [x, y, ((y ** 2) - (x ** 2)) / 4]

min_value = -30
max_value = 30
step = 5
thickness = 0.5

points = [[
paraboloid(x / 10, y / 10)
for x in range(min_value, max_value, step)
] for y in range(min_value, max_value, step)]

solid = surface(points, thickness)
show_object(solid)
``````

``````from math import cos, sqrt, radians

# 要結合以上的 polyhedron 及 surface

def ripple(x, y):
n = radians(sqrt(x ** 2 + y ** 2))
return [x, y, 30 * (cos(n) + cos(3 * n))]

min_value = -200
max_value = 200
step = 10
thickness = 5

points = [[
ripple(x, y)
for x in range(min_value, max_value, step)
] for y in range(min_value, max_value, step)]

solid = surface(points, thickness)
show_object(solid)
``````