環面扭結
November 27, 2021在〈曲線與曲面〉中談過,CadQuery 的 Workplane
有個 parametricCurve
方法,可搭配參數方程式來建立邊(Edge)。
cqmore.curve
cqMore 的 cqmore.curve
定義了一些常用的弧線參數方程式,例如,來畫個阿基米德螺線:
from cqmore import Workplane
from cqmore.curve import archimedeanSpiral
a = 1
b = 1
spiral = (Workplane()
.parametricCurve(
lambda t: archimedeanSpiral(t, a, b),
stop = 4
)
)
parametricCurve
需要的是首參數為 t
的函式,因此以上使用了 lambda
函式來銜接 archimedeanSpiral
,這會畫出以下的圖形:
如果你覺得自行使用 lambda
來銜接不方便,cqmore.curve
提供了 parametricEquation
,可以指定弧線函式、參數,它傳回的函式就可以適用於 parametricCurve
,例如:
from cqmore import Workplane
from cqmore.curve import archimedeanSpiral, parametricEquation
a = 1
b = 1
spiral = (Workplane()
.parametricCurve(
parametricEquation(archimedeanSpiral, a, b),
stop = 4
)
)
當然,像 archimedeanSpiral
這類函式,只不過是就是給定數值傳回對應的結果罷了,因此,要用來建立不連線的風格,也是可以的:
from cqmore import Workplane
from cqmore.curve import archimedeanSpiral
a = 1
b = 1
spiral = (Workplane()
.polyline([
archimedeanSpiral(t / 360, 1, 1)
for t in range(0, 360 * 4, 30)
])
)
這會畫出以下結果:
建立環面扭結
cqmore.curve
有個 torusKnot
,可以用來建立環面扭結(Torus knot),來建個切面為星形的吧!
from cqmore import Workplane
from cqmore.curve import torusKnot, parametricEquation
from cqmore.polygon import star
from cadquery import Plane, Vector
def torus_knot(p, q):
origin = torusKnot(0, p = p, q = q)
v1 = Vector(*torusKnot(0.9, p = p, q = q))
v2 = Vector(*torusKnot(0.1, p = p, q = q))
return (Workplane(Plane(origin = origin, normal = (v2 - v1)))
.makePolygon([(p[0] * 0.5, p[1] * 0.5) for p in star()])
.sweep(
Workplane().parametricCurve(
parametricEquation(torusKnot, p = p, q = q)
),
auxSpine = Workplane().rect(1, 1)
)
)
p = 3
q = 2
knot = torus_knot(p, q)
先來看看這會畫出什麼:
若是運用 Workplane
本身的 sweep
來建立模型的話,難點之一在於如何讓星形面與扭結的路徑正交,這邊使用了扭結 t
為 0 時的點作為原點,0.1 及 0.9 時的點定義向量,作為建立 Workplane
時指定的平面法向量。
另一個難點是為了讓扭結可以整個接合,設定了 auxSpine
參數,簡單來說,想像一下你拿著一個環穿過一條曲線,除了環在轉動過程,要與曲線要正交的問題之外,還有一個問題是,你的環繞著本身的法向量要怎麼轉動,如果不指定 auxSpine
,sweep
預設就只能根據給定的曲線資訊來轉動,這會造成環面扭結的切面在 0 度與 360 度處不接合。
auxSpine
可以指定一個固定的副法向量計算依據,每次要轉動環本身時會用來作為參考,你可以想像一下,環上有個標示,每次轉動環時,標示都要朝著某個固定點,轉了一圈後,環上的標示位置與一開始的位置也要是相同。
這個問題跟〈玩轉 p5.js〉介紹路徑擠出時的討論有點類似,有興趣也可以參考那邊的三篇文件。