實作 polyhedron


在〈操作 BREP 實例〉中,基於頂點與面索引,建立了一個方塊,雖然算是蠻低階的操作,然而,若能搭配一些演算,自動地生成頂點與面索引,進一步地再基於頂點與面索引來建立實體,兩者結合,可以讓模型建立具有極高的彈性。

在 OpenSCAD 中有個 polyhedron 模組,就可以基於頂點與面索引建立 3D 模型,也因為有這個模組,我的 dotSCAD 才能提供更多高階操作,甚至是具有「軟」表面的模型。

那麼,就來將〈操作 BREP 實例〉中最後一個範例重構,定義一個 polyhedron 函式:

from cadquery import Vector, 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
        )
    )

這個函式的 pointsfaces 可以接受頂點與面索引清單,型態只要是可迭代物件,faces 要求共平面、逆時針順序,最後傳回一個 Solid 實體。

例如,〈操作 BREP 實例〉中最後一個範例,有了 polyhedron,就可以如下建立:

# 結合方才的 polyhedron

points = (
    (10, -10, 0),
    (10, 10, 0),
    (-10, 10, 0),
    (-10, -10, 0),
    (10, -10, 10),
    (10, 10, 10),
    (-10, 10, 10),
    (-10, -10, 10)
)

faces = (
    (0, 3, 2, 1), 
    (4, 5, 6, 7), 
    (0, 1, 5, 4), 
    (3, 7, 6, 2), 
    (0, 4, 7, 3), 
    (1, 2, 6, 5)
)

solid = polyhedron(points, faces)
show_object(solid)

執行結果如下:

實作 polyhedron

faces 只要共平面就可以了,例如,底下的金字塔混合了三角面與四邊形面:

# 結合方才的 polyhedron

points = (
    # XY 平面上四個頂點
    (10, 10, 0), (10, -10, 0), (-10, -10, 0), (-10, 10,0), 
    # 金字塔尖端
    (0, 0, 10)
)

faces = (
    # 底部的四邊形
    (0, 1, 2, 3), 
    (4, 1, 0), (4, 2, 1), (4, 3, 2), (4, 0,3),  # 四個三角面
)

solid = polyhedron(points, faces)
show_object(solid)

這會建立以下的模型:

實作 polyhedron

若不確定頂點間是否形成共平面,那麼就全部使用三角面;既然如此,就來個全部都是三角面的正四面體:

# 結合方才的 polyhedron

points = (
    (5, -5, -5), (-5, 5, -5), (5, 5, 5), (-5, -5, 5)
)

faces = (
    (0, 1, 2), (0, 3, 1), (1, 3, 2), (0, 2, 3)
)

solid = polyhedron(points, faces)
show_object(solid)

這會建立以下的模型:

實作 polyhedron