Helicatenoid2
Weaving a transformable curved surface from catenoid to helicoid. You can buy the kit via my Booth site!
Load packages
using Luxor
using IntervalSets
using BasicBSpline
using BasicBSplineFitting
using StaticArrays
using ElasticSurfaceEmbedding
using LinearAlgebra
Define the shape of the surface
const N = 8
const J = 1
f0(s) = max(-abs(s+1/2N-1)-(1/2N-1), 0)
f1(s) = -1/2+f0(mod(s-J/N, 2))
f2(s) = 1/2-f0(mod(s-1-J/N, 2))
f2 (generic function with 1 method)
0≤u≤2π, -π/2≤v≤π/2 0≤s≤2, 0≤t≤1
u(s,t) = π*s
v(s,t) = π*(f1(s)*(1-t) + t*f2(s))
catenoid(u,v) = SVector(cos(u)*cosh(v),sin(u)*cosh(v),v)
ElasticSurfaceEmbedding.𝒑₍₀₎(s,t) = catenoid(u(s,t), v(s,t))
Compute the shape of the embeddings
splitat = [-1/N, -1/2N, 0, 1/2N, 1/N, 1, 1+1/2N, 1+1/N]
steptree = StepTree()
for shift in [0, -1/N, -2/N, -3/N]
initial_state!(steptree, (0+shift..2+shift, 0..1), splitat)
newton_onestep!(steptree, fixingmethod=:fix5points)
newton_onestep!(steptree, fixingmethod=:fix3points)
newton_onestep!(steptree)
refinement!(steptree, p₊=(0,1), k₊=ElasticSurfaceEmbedding.suggest_knotvector(steptree))
for _ in 1:5 newton_onestep!(steptree) end
pin!(steptree)
end
Helper functions to export svg images
function create_bezierpath(C::BSplineManifold{1,(3,),Point})
P = bsplinespaces(C)[1]
k = knotvector(P)
k′ = 3*unique(k) + k[[1,end]]
P′ = BSplineSpace{3}(k′)
C′ = refinement(C,P′)
a′ = controlpoints(C′)
n′ = dim(P′)
m = (n′-1) ÷ 3
bezierpath = BezierPath([BezierPathSegment(a′[3i-2], a′[3i-1], a′[3i], a′[3i+1]) for i in 1:m])
return bezierpath
end
function svector2point(M::BSplineManifold)
P = bsplinespaces(M)
a = controlpoints(M)
a′ = [Point(p[1], -p[2])*100/π for p in a]
M′ = BSplineManifold(a′, P)
return M′
end
svector2point (generic function with 1 method)
Settings for export
xlims=(-2,2)
ylims=(-2,2)
unitlength = (100, "mm")
width = (xlims[2] - xlims[1]) * unitlength[1]
height = (ylims[2] - ylims[1]) * unitlength[1]
400
Export embeddings
mkpath("helicatenoid2")
for i in 1:(N+1)÷2
filepath = joinpath("helicatenoid2", "embedding-$(i).svg")
M = svector2point(steptree.steps[10i].manifold)
D¹ = domain(bsplinespaces(M)[1])
D² = domain(bsplinespaces(M)[2])
u²₋ = minimum(D²)
u²₊ = maximum(D²)
Drawing(width, height, filepath)
origin()
background("white")
sethue("red")
C = M(:,u²₋)
path = create_bezierpath(C)
drawbezierpath(path, :stroke)
C = M(:,u²₊)
path = create_bezierpath(C)
drawbezierpath(path, :stroke)
p1 = controlpoints(M)[begin,begin]
p2 = controlpoints(M)[begin,end]
p3 = controlpoints(M)[end,begin]
p4 = controlpoints(M)[end,end]
v12 = p1-p2
q1 = p1 - Point(v12[2],-v12[1])/norm(v12) * 6
q2 = p2 - Point(v12[2],-v12[1])/norm(v12) * 6
line(p1,q1)
line(q2)
line(p2)
strokepath()
v34 = p3-p4
q3 = p3 + Point(v34[2],-v34[1])/norm(v34) * 6
q4 = p4 + Point(v34[2],-v34[1])/norm(v34) * 6
line(p3,q3)
line(q4)
line(p4)
strokepath()
finish()
preview()
script = read(filepath, String)
lines = split(script, "\n")
lines[2] = replace(lines[2],"pt\""=>"mm\"")
write(filepath, join(lines,"\n"))
end
The output files will be saved as embedding-$(i).svg
.
References
This page was generated using DemoCards.jl and Literate.jl.