3D Mesh Processing and Visualization in Julia
This workflow loads an STL file, remeshes it, generates a tetrahedral mesh with Gmsh, converts it to a Ferrite grid, and visualizes it with an interactive slice.
Dependencies
julia
using GmshSTL
using FerriteGmsh
using Geogram, FileIO, Comodo, Comodo.GLMakie
using ComodoFerrite, Comodo.StatisticsInitialization
julia
GLMakie.closeall()Load STL Geometry
julia
fileName_mesh = joinpath(GmshSTL_dir(), "assets", "stl", "cube_3holes.stl")
M = load(fileName_mesh)
F = tofaces(GeometryBasics.faces(M))
V = topoints(GeometryBasics.coordinates(M))Original Mesh Info
julia
nb_pts = 5000
@info "Number of vertices in original mesh (STL)" length(V)
@info "Original STL file volume" surfacevolume(F, V)Preprocessing & Remeshing
julia
F, V, _, _ = mergevertices(F, V)
F, V = ggremesh(
F, V;
nb_pts = nb_pts,
remesh_anisotropy = 3.0,
remesh_gradation = 0.1,
pre_max_hole_area = 0,
pre_max_hole_edges = 0,
post_max_hole_area = 0,
quiet = 0,
suppress = true
)Gmsh Volume Meshing
julia
algorithm3d = 1.0
min_length = 2.0
max_length = 4.0
optimize_netgen = 1.0
quality = 2.0
msh_version = 2.2
angle_tol = 0.05
verbosity = 2
output_path = joinpath(GmshSTL_dir(), "assets", "msh", "cube_3holes.msh")
result = gmsh_mesh_stl(
F, V,
algorithm3d,
min_length,
max_length,
optimize_netgen,
quality,
msh_version,
angle_tol,
verbosity,
output_path
)Convert to Ferrite Grid
julia
grid = FerriteGmsh.togrid(output_path)
E, V, F, Fb, CFb_type = FerriteToComodo(grid)Mesh Volume Check
julia
@info "Mesh volume" sum(tetvolume(E, V))Surface Extraction
julia
Fbs, Vbs = separate_vertices(Fb, V)
Cbs_V = simplex2vertexdata(Fbs, CFb_type)
M = GeometryBasics.Mesh(Vbs, Fbs)Visualization
julia
fig = Figure(size = (1000, 800))
ax1 = AxisGeom(fig[1, 1], title = "Mesh")
meshplot!(ax1, Fbs, Vbs; strokewidth = 2)
ax2 = AxisGeom(fig[1, 2], title = "Cut view of mesh")
hp3 = meshplot!(ax2, Fbs, Vbs; strokewidth = 2, color = :white)Interactive Slice
julia
VE = simplexcenter(E, V)
ZE = [v[3] for v in VE]
Z = [v[3] for v in V]
zMax = maximum(Z)
zMin = minimum(Z)
numSlicerSteps = 10
stepRange = range(zMin, zMax, numSlicerSteps)
hSlider = Slider(fig[2, :],
range = stepRange,
startvalue = mean(stepRange),
linewidth = 30
)Slice Update
julia
on(hSlider.value) do z
B = ZE .<= z
indShow = findall(B)
if isempty(indShow)
hp3.visible = false
else
hp3.visible = true
Fs = element2faces(E[indShow])
Fs, Vs = separate_vertices(Fs, V)
Ms = GeometryBasics.Mesh(Vs, Fs)
hp3[1] = Ms
end
endSlider Control
julia
slidercontrol(hSlider, ax2)Display
julia
display(GLMakie.Screen(), fig)