Skip to content

Commit

Permalink
Refactor makie recipes
Browse files Browse the repository at this point in the history
  • Loading branch information
juliohm committed Nov 23, 2023
1 parent 8d164b6 commit 1b8ff0f
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 238 deletions.
229 changes: 49 additions & 180 deletions ext/cartesiangrid.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,155 +6,67 @@ Makie.plottype(::CartesianGrid) = Viz{<:Tuple{CartesianGrid}}

function Makie.plot!(plot::Viz{<:Tuple{CartesianGrid}})
# retrieve parameters
grid = plot[:object][]
color = plot[:color][]
showfacets = plot[:showfacets][]
ndim = embeddim(grid)

# different recipes for Cartesian grids
# with 1D, 2D, 3D elements
if color isa AbstractVector
# visualize grid as heatmap or volume
if ndim == 1
vizgrid1D!(plot)
elseif ndim == 2
if length(color) == nvertices(grid)
vizmesh2D!(plot)
else
vizgrid2D!(plot)
end
elseif ndim == 3
vizgrid3D!(plot)
end
else
# create the smallest mesh of simplices
vizgrid!(plot)
end

if showfacets
# create minimum number of segments
vizsegs!(plot)
end
end

function vizgrid1D!(plot)
grid = plot[:object]
color = plot[:color]
alpha = plot[:alpha]
colorscheme = plot[:colorscheme]
showfacets = plot[:showfacets]
facetcolor = plot[:facetcolor]

# process color spec into colorant
colorant = Makie.@lift process($color, $colorscheme, $alpha)

cparams = Makie.@lift let
nd = embeddim($grid)
or = coordinates(minimum($grid))
sp = spacing($grid)
sz = size($grid)

xs, ys = cartesiancenters(or, sp, sz, nd)

xs⁻ = [(xs .- sp[1] / 2); (last(xs) + sp[1] / 2)]
ys⁻ = [ys; last(ys)]

points = [Point(x, y) for (x, y) in zip(xs⁻, ys⁻)]
mesh = SimpleMesh(points, topology($grid))

colors = [$colorant; last($colorant)]

mesh, colors
end

# unpack observable of parameters
mesh = Makie.@lift $cparams[1]
colors = Makie.@lift $cparams[2]

# rely on recipe for simplices
viz!(plot, mesh, color=colors, showfacets=showfacets, facetcolor=facetcolor)
end

function vizgrid2D!(plot)
grid = plot[:object]
color = plot[:color]
alpha = plot[:alpha]
colorscheme = plot[:colorscheme]

# process color spec into colorant
colorant = Makie.@lift process($color, $colorscheme, $alpha)

cparams = Makie.@lift let
nd = embeddim($grid)
or = coordinates(minimum($grid))
sp = spacing($grid)
sz = size($grid)

xs, ys = cartesiancenters(or, sp, sz, nd)

C = reshape($colorant, sz)

xs, ys, C
end

# unpack observable of parameters
xs = Makie.@lift $cparams[1]
ys = Makie.@lift $cparams[2]
C = Makie.@lift $cparams[3]

Makie.heatmap!(plot, xs, ys, C)
end

function vizgrid3D!(plot)
grid = plot[:object]
color = plot[:color]
alpha = plot[:alpha]
colorscheme = plot[:colorscheme]

# process color spec into colorant
colorant = Makie.@lift process($color, $colorscheme, $alpha)

cparams = Makie.@lift let
nd = embeddim($grid)
or = coordinates(minimum($grid))
sp = spacing($grid)
sz = size($grid)

xs, ys, zs = cartesiancenters(or, sp, sz, nd)

xs⁺ = xs .+ sp[1] / 2
ys⁺ = ys .+ sp[2] / 2
zs⁺ = zs .+ sp[3] / 2

coords = [(x, y, z) for z in zs⁺ for y in ys⁺ for x in xs⁺]

marker = Makie.Rect3(-1 .* sp, sp)

coords, marker
# number of dimensions, vertices and colors
nd = Makie.@lift embeddim($grid)
nv = Makie.@lift nvertices($grid)
nc = Makie.@lift $colorant isa AbstractVector ? length($colorant) : 1

# origin, spacing and size of grid
or = Makie.@lift coordinates(minimum($grid))
sp = Makie.@lift spacing($grid)
sz = Makie.@lift size($grid)

# coordinates of centroids
xyz = [(Makie.@lift range($or[i] + $sp[i] / 2, step=$sp[i], length=$sz[i])) for i in 1:nd[]]

# dispatch different recipes
if nc[] == 1
# visualize bounding box with a single
# color for maximum performance
bbox = Makie.@lift boundingbox($grid)
viz!(plot, bbox, color=colorant)
else
# search other visualization methods
if nd[] == 2
if nc[] == nv[]
# visualize as a simple mesh so that
# colors can be specified at vertices
vizmesh2D!(plot)
else
# visualize as built-in heatmap
C = Makie.@lift reshape($colorant, $sz)
Makie.heatmap!(plot, xyz[1], xyz[2], C)
end
elseif nd[] == 3
if nc[] == nv[]
throw(ErrorException("not implemented"))
else
# visualize as built-in meshscatter
xs = Makie.@lift $(xyz[1]) .+ $sp[1] / 2
ys = Makie.@lift $(xyz[2]) .+ $sp[2] / 2
zs = Makie.@lift $(xyz[3]) .+ $sp[3] / 2
cs = Makie.@lift [(x, y, z) for z in $zs for y in $ys for x in $xs]
re = Makie.@lift Makie.Rect3(-1 .* $sp, $sp)
Makie.meshscatter!(plot, cs, marker=re, markersize=1, color=colorant)
end
else
throw(ErrorException("can only visualize 2D and 3D grids"))
end
end

# unpack observable of parameters
coords = Makie.@lift $cparams[1]
marker = Makie.@lift $cparams[2]

Makie.meshscatter!(plot, coords, marker=marker, markersize=1, color=colorant)
end

function vizgrid!(plot)
grid = plot[:object]
color = plot[:color]
alpha = plot[:alpha]

mesh = Makie.@lift let
nd = embeddim($grid)
or = coordinates(minimum($grid))
sp = spacing($grid)
sz = size($grid)

cartesianmesh(or, sp, sz, nd)
# optimized visualization of facets
if showfacets[]
vizsegs!(plot)
end

viz!(plot, mesh, color=color, alpha=alpha, showfacets=false)
end

function vizsegs!(plot)
Expand All @@ -177,28 +89,6 @@ function vizsegs!(plot)
Makie.lines!(plot, xyz..., color=facetcolor, linewidth=segmentsize)
end

# helper function to create the smallest mesh
# of simplices covering the Cartesian grid
function cartesianmesh(or, sp, sz, nd)
if nd == 1
A = Point2(or[1], 0) + Vec2(0, 0)
B = Point2(or[1], 0) + Vec2(sp[1] * sz[1], 0)
points = [A, B]
connec = connect.([(1, 2)])
SimpleMesh(points, connec)
elseif nd == 2
A = Point2(or) + Vec2(0, 0)
B = Point2(or) + Vec2(sp[1] * sz[1], sp[2] * sz[2])
discretize(Box(A, B))
elseif nd == 3
A = Point3(or) + Vec3(0, 0, 0)
B = Point3(or) + Vec3(sp[1] * sz[1], sp[2] * sz[2], sp[3] * sz[3])
boundary(Box(A, B))
else
throw(ErrorException("not implemented"))
end
end

# helper function to create a minimum number
# of line segments within Cartesian grid
function cartesiansegments(or, sp, sz, nd)
Expand Down Expand Up @@ -247,24 +137,3 @@ function cartesiansegments(or, sp, sz, nd)
throw(ErrorException("not implemented"))
end
end

# helper function to create the center of
# the elements of the Cartesian grid
function cartesiancenters(or, sp, sz, nd)
if nd == 1
xs = range(or[1] + sp[1] / 2, step=sp[1], length=sz[1])
ys = fill(0.0, sz[1])
xs, ys
elseif nd == 2
xs = range(or[1] + sp[1] / 2, step=sp[1], length=sz[1])
ys = range(or[2] + sp[2] / 2, step=sp[2], length=sz[2])
xs, ys
elseif nd == 3
xs = range(or[1] + sp[1] / 2, step=sp[1], length=sz[1])
ys = range(or[2] + sp[2] / 2, step=sp[2], length=sz[2])
zs = range(or[3] + sp[3] / 2, step=sp[3], length=sz[3])
xs, ys, zs
else
throw(ErrorException("not implemented"))
end
end
61 changes: 3 additions & 58 deletions ext/simplemesh.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,51 +9,15 @@ function Makie.plot!(plot::Viz{<:Tuple{SimpleMesh}})
mesh = plot[:object][]
rank = paramdim(mesh)

# different recipes for meshes with
# 1D, 2D, 3D, ... ND simplices
if rank == 1
# visualize segments
vizmesh1D!(plot)
elseif rank == 2
# visualize polygons
if rank == 2
vizmesh2D!(plot)
elseif rank == 3
# visualize polyhedra
vizmesh3D!(plot)
else
throw(ErrorException("can only visualize 2D and 3D meshes"))
end
end

function vizmesh1D!(plot)
mesh = plot[:object]
color = plot[:color]
alpha = plot[:alpha]
colorscheme = plot[:colorscheme]
segmentsize = plot[:segmentsize]

# process color spec into colorant
colorant = Makie.@lift process($color, $colorscheme, $alpha)

# retrieve coordinates of segments
coords = Makie.@lift let
topo = topology($mesh)
vert = vertices($mesh)
segmentsof(topo, vert)
end

# repeat colors for vertices of segments
colors = Makie.@lift let
if $colorant isa AbstractVector
c = [$colorant[e] for e in 1:nelements($mesh) for _ in 1:3]
c[begin:(end - 1)]
else
$colorant
end
end

# visualize segments
Makie.lines!(plot, coords, color=colors, linewidth=segmentsize)
end

function vizmesh2D!(plot)
mesh = plot[:object]
color = plot[:color]
Expand Down Expand Up @@ -200,22 +164,3 @@ function vizmesh3D!(plot)
end
vizmany!(plot, meshes)
end

function segmentsof(topo, vert)
dim = embeddim(first(vert))
nan = Vec(ntuple(i -> NaN, dim))
xs = coordinates.(vert)

coords = map(elements(topo)) do e
inds = indices(e)
xs[collect(inds)]
end

reduce((x, y) -> [x; [nan]; y], coords)
end

function segmentsof(topo::GridTopology, vert)
xs = coordinates.(vert)
ip = first(isperiodic(topo))
ip ? [xs; [first(xs)]] : xs
end

0 comments on commit 1b8ff0f

Please sign in to comment.