Last active
October 13, 2023 13:38
-
-
Save stla/5a854243fa64290ec8dc0780db29ef34 to your computer and use it in GitHub Desktop.
Revisions
-
stla revised this gist
Oct 13, 2023 . 1 changed file with 22 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -3,6 +3,7 @@ using LinearAlgebra using MeshViz using GLMakie using Makie using Printf # beta factor function betaF(A, s) @@ -316,8 +317,28 @@ function drawGI(s, r, alpha1, alpha2) [MeshViz.viz!(gtriangle; color=:navy) for gtriangle in gmesh.gyrotriangles] [MeshViz.viz!(gedge; color=:gold) for gedge in gmesh.gyroedges] [MeshViz.viz!(sphere; color=:gold) for sphere in gmesh.spheres] Makie.scale!(ax.scene, 1.75, 1.75, 1.75) Makie.rotate!(fig.scene, Meshes.Vec3f(1, 0, 0), alpha1) Makie.rotate!(ax.scene, Meshes.Vec3f(0, 0, 1), alpha2) Makie.save("gyroIcosahedron.png", fig) end function animGI(nplots, r, alpha1, alpha2) s_ = LinRange(0.6, 0.8, nplots) for i in 1:nplots gmesh = gyromesh(icosahedron, s_[i], r) unitsphere = Meshes.discretize(Meshes.Sphere((0, 0, 0), 1)) fig, ax, plt = MeshViz.viz( # invisible bounding sphere unitsphere; alpha = 0 ) ax.show_axis = false [MeshViz.viz!(gtriangle; color=:navy) for gtriangle in gmesh.gyrotriangles] [MeshViz.viz!(gedge; color=:gold) for gedge in gmesh.gyroedges] [MeshViz.viz!(sphere; color=:gold) for sphere in gmesh.spheres] Makie.scale!(ax.scene, 1.75, 1.75, 1.75) Makie.rotate!(fig.scene, Meshes.Vec3f(1, 0, 0), alpha1) Makie.rotate!(ax.scene, Meshes.Vec3f(0, 0, 1), alpha2) png = @sprintf "zzpic%03d.png" i Makie.save(png, fig) end end -
stla revised this gist
Oct 13, 2023 . 1 changed file with 4 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -122,10 +122,12 @@ function edgeslist(mesh) end # gyrotube, made of spheres function gyrotube(A, B, s, radius; n = 200) centers = gyrosegment(A, B, s; n = n) spheres = [ Meshes.discretize( Meshes.Sphere(ctr, radius), Meshes.RegularDiscretization(20) ) for ctr in centers ] reduce(Meshes.merge, spheres) -
stla created this gist
Oct 12, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,321 @@ import Meshes using LinearAlgebra using MeshViz using GLMakie using Makie # beta factor function betaF(A, s) 1.0 / √(1 + LinearAlgebra.norm_sqr(A) / (s*s)) end # gyroaddition function gyroadd(A, B, s) betaA = betaF(A, s) betaB = betaF(B, s) ( 1 + (betaA / (1 + betaA)) * dot(A, B) / (s*s) + (1 - betaB) / betaB ) * A + B end # scalar gyromultiplication function gyroscalar(r, A, s) Anorm = norm(A) (s / Anorm) * sinh(r * asinh(Anorm / s)) * A end # point of coordinate t on the gyroline (AB) function gyroABt(A, B, t, s) gyroadd(A, gyroscalar(t, gyroadd(-A, B, s), s), s) end # gyromidpoint function gyromidpoint(A, B, s) gyroABt(A, B, 0.5, s) end # gyrosegment function gyrosegment(A, B, s; n=50) A, B = Meshes.coordinates(A), Meshes.coordinates(B) [Meshes.Point(gyroABt(A, B, t, s)) for t in LinRange(0, 1, n)] end # edge index (I don't remember what is it...) function edgeindex(from, to, size) row = min(from, to) col = max(from, to) Int(row * size - (row * (row + 1)) / 2 - (size - col)) end # gyrosubdivision function gyrosubdiv(s, vertices, triangles) nv = length(vertices) nt = length(triangles) nvmax = Int(nv + (nv * (nv + 1)) / 2) newvertices = fill([0.0, 0.0, 0.0], nvmax) for i in 1:nv newvertices[i] = vertices[i] end vcnt = nv em = fill(-1, Int(nv * (nv + 1) / 2)) newtriangles = Vector{Tuple{Int,Int,Int}}(undef, 4 * nt) for i in 1:nt local ithis, iprev, inext visited = Int[] for j in 1:3 iprev = triangles[i][((j + 1) % 3) + 1] ithis = triangles[i][j] inext = triangles[i][(j % 3) + 1] mindex = edgeindex(ithis, inext, nv) enext = em[mindex] if enext == -1 vcnt = vcnt + 1 enext = vcnt em[mindex] = enext end mindex = edgeindex(iprev, ithis, nv) eprev = em[mindex] if eprev == -1 vcnt = vcnt + 1 eprev = vcnt em[mindex] = eprev end newtriangles[(i-1)*4 + j] = (enext, ithis, eprev) newvertices[enext] = in(enext, visited) ? gyromidpoint(newvertices[enext], vertices[ithis], s) : vertices[ithis] newvertices[eprev] = in(eprev, visited) ? gyromidpoint(newvertices[eprev], vertices[ithis], s) : vertices[ithis] push!(visited, enext, eprev) end newtriangles[(i-1)*4 + 4] = ( em[edgeindex(inext, iprev, nv)], em[edgeindex(ithis, inext, nv)], em[edgeindex(iprev, ithis, nv)] ) end return (vertices = newvertices[1:vcnt], triangles = newtriangles) end # gyrotriangle function gyrotriangle(A, B, C, s; depth=3) ABC = [Meshes.coordinates(A), Meshes.coordinates(B), Meshes.coordinates(C)] triangle = (1, 2, 3) if iseven(depth) triangle = reverse(triangle) end subdiv = gyrosubdiv(s, ABC, [triangle]) for _ in 1:depth subdiv = gyrosubdiv(s, subdiv...) end vertices = [Meshes.Point(v...) for v in subdiv.vertices] connectivities = Meshes.connect.(subdiv.triangles, Meshes.Triangle) Meshes.SimpleMesh(vertices, connectivities) end # edges of a mesh function edgeslist(mesh) topo = convert(Meshes.HalfEdgeTopology, Meshes.topology(mesh)) edges_map = Meshes.Boundary{1,0}(topo) edges = [edges_map(i) for i in 1:Meshes.nfacets(topo)] vertices = mesh.vertices [(vertices[edge[1]], vertices[edge[2]]) for edge in edges] end # gyrotube, made of spheres function gyrotube(A, B, s, radius; n = 1000) centers = gyrosegment(A, B, s; n = n) spheres = [ Meshes.discretize(Meshes.Sphere(ctr, radius)) for ctr in centers ] reduce(Meshes.merge, spheres) end # merge duplicated vertices of a mesh function gather(mesh) # get mesh vertices points = Meshes.vertices(mesh) npoints = length(points) # Boolean vector indicating the duplicated vertices duplicated = fill(false, npoints) # dictionary to map the old indices to the new indices newindices = Dict{Int64,Int64}() # initialize new indices newindex = 1 # iterate over vertices for index in 1:(npoints-1) if !duplicated[index] tail = points[(index+1):npoints] duplicates = index .+ findall(==(points[index]), tail) duplicated[duplicates] .= true push!(duplicates, index) for i in duplicates newindices[i] = newindex end newindex = newindex + 1 end end # if the last vertex is not a duplicate, add it to the dictionary if npoints ∉ keys(newindices) #!haskey(newindices, npoints) newindices[npoints] = newindex end # get the faces topo = convert(Meshes.HalfEdgeTopology, Meshes.topology(mesh)) ∂₂₀ = Meshes.Boundary{2,0}(topo) nfaces = Meshes.nelements(topo) # vector to store the connectivities connec = Vector{Meshes.Connectivity}(undef, 0) # iterate over the faces for f in 1:nfaces face = ∂₂₀(f) toconnect = [newindices[i] for i in face] c = Meshes.connect(tuple(toconnect...)) push!(connec, c) end Meshes.SimpleMesh(points[.!duplicated], connec) end """ gyromesh(triangles, curvature, edgeradius; depth=2) Gyromesh from a vector of triangles. # Arguments - `triangles`: vector made of vectors of three points - `curvature`: hyperbolic curvature - `edgeradius`: radius of the gyroedges (gyrotubes) - `depth`: number of iterations """ function gyromesh(triangles::Vector, curvature, edgeradius; depth = 2) meshes = [ Meshes.SimpleMesh(tr, Meshes.connect.([(1, 2, 3)])) for tr in triangles ] mesh = gather(reduce(Meshes.merge, meshes)) edges = edgeslist(mesh) gyroedges = [ gyrotube(edge[1], edge[2], curvature, edgeradius) for edge in edges ] gyrotriangles = [ gyrotriangle(tr..., curvature; depth=depth) for tr in triangles ] spheres = [ Meshes.discretize(Meshes.Sphere(pt, edgeradius*1.5)) for pt in Meshes.vertices(mesh) ] (gyroedges = gyroedges, gyrotriangles = gyrotriangles, spheres = spheres) end """ gyromesh(m, curvature, edgeradius; depth=2) Gyromesh from a triangle mesh. # Arguments - `m`: a triangle mesh - `curvature`: hyperbolic curvature - `edgeradius`: radius of the gyroedges - `depth`: number of iterations """ function gyromesh(m::Meshes.Mesh, curvature, edgeradius; depth = 2) triangles = Meshes.vertices.(collect(m)) gyromesh(triangles, curvature, edgeradius; depth = depth) end # test #### #= a = 1 p1 = Meshes.Point(a, -a, -a) p2 = Meshes.Point(a, a, a) p3 = Meshes.Point(-a, -a, a) p4 = Meshes.Point(-a, a, -a) mesh = Meshes.SimpleMesh( [p1, p2, p3, p4], Meshes.connect.([(1,2,3), (1,2,4), (1,3,4), (2,3,4)], Meshes.Triangle) ) gmesh = gyromesh(mesh, 0.7, 0.01) function draw(gmesh) [MeshViz.viz!(gtriangle; color=:green) for gtriangle in gmesh.gyrotriangles] [MeshViz.viz!(gedge; color=:yellow) for gedge in gmesh.gyroedges] [MeshViz.viz!(sphere; color=:yellow) for sphere in gmesh.spheres] return 0 end MeshViz.viz(gmesh.gyrotriangles[1]; color = :green) =# C0 = (1 + sqrt(5)) / 4 vertices = Meshes.Point.([ (0.5, 0.0, C0), (0.5, 0.0, -C0), (-0.5, 0.0, C0), (-0.5, 0.0, -C0), (C0, 0.5, 0.0), (C0, -0.5, 0.0), (-C0, 0.5, 0.0), (-C0, -0.5, 0.0), (0.0, C0, 0.5), (0.0, C0, -0.5), (0.0, -C0, 0.5), (0.0, -C0, -0.5) ]) faces = map(f -> f .+ 1, [ [0, 2, 10], [0, 10, 5], [0, 5, 4], [0, 4, 8], [0, 8, 2], [3, 1, 11], [3, 11, 7], [3, 7, 6], [3, 6, 9], [3, 9, 1], [2, 6, 7], [2, 7, 10], [10, 7, 11], [10, 11, 5], [5, 11, 1], [5, 1, 4], [4, 1, 9], [4, 9, 8], [8, 9, 6], [8, 6, 2] ]) triangles = [vertices[f] for f in faces] icosahedron = Meshes.SimpleMesh( vertices, Meshes.connect.([tuple(f...) for f in faces], Meshes.Triangle) ) function drawGI(s, r, alpha1, alpha2) gmesh = gyromesh(icosahedron, s, r) unitsphere = Meshes.discretize(Meshes.Sphere((0, 0, 0), 1)) fig, ax, plt = MeshViz.viz( # invisible bounding sphere unitsphere; alpha = 0 ) ax.show_axis = false [MeshViz.viz!(gtriangle; color=:navy) for gtriangle in gmesh.gyrotriangles] [MeshViz.viz!(gedge; color=:gold) for gedge in gmesh.gyroedges] [MeshViz.viz!(sphere; color=:gold) for sphere in gmesh.spheres] Makie.scale!(ax.scene, 1.65, 1.65, 1.65) Makie.rotate!(fig.scene, Meshes.Vec3f(1, 0, 0), alpha1) Makie.rotate!(ax.scene, Meshes.Vec3f(0, 0, 1), alpha2) Makie.save("gyroIcosahedron.png", fig) end