Given a 3D curve $\vec{r}(t) = (x(t), y(t), z(t)), t \in I=[0,1]$, Tubify[ {x, y, z}, a] turns it into a tube around the curve. The Mathematica Tube[] has similar function (works on lines). The essential thing is to find the unit circle in the normal plane for each point (Shown in Fig. 1). The tangential vector is simply $\vec{\alpha} = \vec{r}'/|\vec{r}'|$, where $\vec{r}' = \mathrm{d} \vec{r}/\mathrm{d}t$. The normal vector is $\vec \beta = \vec{\alpha}' / |\vec{\alpha}'| = \frac{\vec{r}'' |\vec{r}'|^2 - \vec{r}' \vec{r}'\cdot\vec{r}''}{|\vec{r}'| \sqrt{|\vec{r}''|^2 |\vec{r}'|^2 - (\vec{r}'\cdot\vec{r}'')^2} }$. The binormal vector is $\vec{\gamma} = \vec{\alpha} \times \vec{\beta} = \frac{\vec{r}' \times \vec{r}'' }{\sqrt{|\vec{r}''|^2 |\vec{r}'|^2 - (\vec{r}'\cdot\vec{r}'')^2} } $.
|
Fig. 1: black, $\vec{\alpha}$, green $\vec{\beta}$, blue $\vec{\gamma}$. |
Tubify[{x_, y_, z_}, r_] :=
({x[#1], y[#1], z[#1]}
+ (r[#1] Cos[#2])/
Norm[(Norm[{x'[#1], y'[#1], z'[#1]}]^2 {x''[#1], y''[#1],
z''[#1]} - {x'[#1], y'[#1], z'[#1]}.{x''[#1], y''[#1],
z''[#1]} {x'[#1], y'[#1], z'[#1]})] (Norm[{x'[#1], y'[#1],
z'[#1]}]^2 {x''[#1], y''[#1],
z''[#1]} - {x'[#1], y'[#1], z'[#1]}.{x''[#1], y''[#1],
z''[#1]} {x'[#1], y'[#1], z'[#1]})
+ (r [#1] Sin[#2] )/
Norm[{-z'[#1]*y''[#1] + z''[#1]*y'[#1],
z'[#1]*x''[#1] - z''[#1]*x'[#1], -y'[#1]*x''[#1] +
x'[#1]*y''[#1]}] {-z'[#1]*y''[#1] + z''[#1]*y'[#1],
z'[#1]*x''[#1] - z''[#1]*x'[#1], -y'[#1]*x''[#1] +
x'[#1]*y''[#1]}) &
All the arguments are functions.
Example 1:
Show[ParametricPlot3D[
Tubify[{(2 + Cos[3 #]) Cos[ #] &, (2 + Cos[3 #]) Sin[#] &,
Sin[3 #] &}, 0.25 &][u, v],
{u, 0, 2 Pi}, {v, 0, 2 Pi}, PlotStyle -> Opacity[0.2],
Mesh -> None, Boxed -> True, Axes -> False, BoxRatios -> Automatic,
PerformanceGoal -> "Quality", PlotPoints -> 80, MaxRecursion -> 0,
PlotLabel ->
Style[TraditionalForm /@ {(2 + Cos[3 t]) Cos[
t], (2 + Cos[3 t]) Sin[t], Sin[3 t]}, 20]
],
ParametricPlot3D[{(2 + Cos[3 u]) Cos[ u], (2 + Cos[3 u]) Sin[u],
Sin[3 u]}, {u, 0, 2 Pi},
PlotStyle -> Directive[{Red, Opacity[1], Thick}]], ImageSize -> 600
]
A similar code using Tube[]:
ParametricPlot3D[
{(2 + Cos[3 u]) Cos[ u], (2 + Cos[3 u]) Sin[u],
Sin[3 u]}, {u, 0, 2 Pi}, PlotStyle -> Opacity[0.2],
Mesh -> None, Boxed -> True, Axes -> False, BoxRatios -> Automatic,
PerformanceGoal -> "Quality", PlotPoints -> 80, MaxRecursion -> 0,
PlotLabel ->
Style[TraditionalForm /@ {(2 + Cos[3 t]) Cos[
t], (2 + Cos[3 t]) Sin[t], Sin[3 t]}, 20]
]/.Line[pts_, rest___] :> Tube[pts, 0.1, rest]
|
Fig. 2 |
Example 2, trefoil knot:
Show[ParametricPlot3D[
Tubify[{Sin[#] + 2 Sin[2 #] &, Cos[#] - 2 Cos[2 #] &, -Sin[3 #] &},
0.25 &][u, v],
{u, 0, 2 Pi}, {v, 0, 2 Pi}, PlotStyle -> Opacity[0.3],
Mesh -> None, Boxed -> True, Axes -> False, BoxRatios -> Automatic,
PerformanceGoal -> "Quality", PlotPoints -> 100, MaxRecursion -> 0,
PlotLabel -> Style[TraditionalForm /@ trefoil[t], 20]
], ImageSize -> 600
]
|
Fig. 3 Trefoil Knot |
Similarly, we can also define the Frenet's Ribbon:
Ribbonize[{x_, y_, z_}, r_] :=
({x[#1], y[#1], z[#1]}
+ r [#1] #2 /
Norm[{-z'[#1]*y''[#1] + z''[#1]*y'[#1],
z'[#1]*x''[#1] - z''[#1]*x'[#1], -y'[#1]*x''[#1] +
x'[#1]*y''[#1]}] {-z'[#1]*y''[#1] + z''[#1]*y'[#1],
z'[#1]*x''[#1] - z''[#1]*x'[#1], -y'[#1]*x''[#1] +
x'[#1]*y''[#1]}) &
|
Fig. 4, Trefoil Ribbon |
|
Fig. 5, Helix Ribbon |
more examples:
|
Fig. 6, A Seashell Surface |
|
Fig. 7, Double Helix (cf. DNA) |
|
Fig. 8, A Figure-eight Knot |
ParametricPlot3D[
Tubify[{#/Pi Cos[#] &, #/Pi Sin[#] &, #/Pi &}, Sin[#/4] &][u, u*80],
{u, 0, 4 Pi}, PlotStyle -> Directive[{Red, Thick, Opacity[0.8]}],
Mesh -> None, Boxed -> True, Axes -> False, BoxRatios -> Automatic,
PlotRange -> All, PerformanceGoal -> "Quality", MaxRecursion -> 0,
PlotPoints -> 2560, PlotLabel -> Style["", 20],
ImageSize -> 500
]
|
Fig. 9, a coilfied 3D curve |
Have you code for Fig. 9, a coilfied 3D curve
ReplyDeleteSincerely,
Thx
The code above Fig. 9 is what you want.
Delete