# Drawing a tubular path with Meshes.jl (blog post)

**URL:** <https://discourse.julialang.org/t/drawing-a-tubular-path-with-meshes-jl-blog-post/104203>\
**Category:** Community\
**Tags:** plotting\
**Created:** [September 24, 2023, 11:22pm UTC](https://discourse.julialang.org/t/drawing-a-tubular-path-with-meshes-jl-blog-post/104203 "2023-09-24T23:22:37Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![empet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empet/32/221303_2.png) [@empet](https://discourse.julialang.org/u/empet)\
**Post date:** [September 25, 2023, 6:28am UTC](https://discourse.julialang.org/t/drawing-a-tubular-path-with-meshes-jl-blog-post/104203/2 "2023-09-25T06:28:35Z")

</div>

It is much simpler to define a tubular surface of directional curve, γ, using quaternions:

```julia
import ForwardDiff.derivative
import LinearAlgebra: norm, cross
import Rotations.UnitQuaternion

dγ(t)=derivative(γ, t) # t->̇γ(t)
ddγ(t)=derivative(dγ, t) #t->̈γ(t)

#get the tubular surface parameterization:
function tube(γ::T, u::S, v::S; radius=0.1) where {S<:Real, T<:Function}
    tang = dγ(u) #tangent(γ, u)
    ~iszero(tang) || error("null tangent vector!")
    unittan = tang/norm(tang)
    θ = acos(unittan[1])/2
    crossp= [0, -unittan[3], unittan[2]] # cross product [1,0,0] x unittan
    quvect = sin(θ)*crossp/norm(crossp) #3-vector to define the quaternion 
                                          #q=(cos(θ), sin(θ)*unitvect)
    q = isapprox(θ, π/2) ? UnitQuaternion(0, 0, 1, 0) : isapprox(θ, 0) ? 
                   UnitQuaternion(1, 0 , 0, 0) : UnitQuaternion(cos(θ), quvect...)
    _, n₁, n₂, = eachcol(q)
    return γ(u) + radius*cos(v) * n₁ + radius*sin(v) * n₂
end 

```

[Example](https://nbviewer.org/github/empet/Plain-knit-yarns-modeling/blob/main/Plain-Knit-Yarns-modeling.ipynb)

---

_[View the full topic](https://discourse.julialang.org/t/drawing-a-tubular-path-with-meshes-jl-blog-post/104203)._
