A way to display images on meshes which are pretransformed in Makie.jl
This file contains 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 characters
using Makie: GeometryBasics | |
using Makie.GeometryBasics: StructArrays | |
@recipe(MeshImage) do scene | |
Attributes( | |
npoints = 100, | |
space = :data, | |
) | |
end | |
# this inherits all conversions for `Image`, | |
# if no specialized conversion for `MeshImage` is found | |
Makie.conversion_trait(::Type{<: MeshImage}) = Image | |
function apply_transform!(f, structarray::StructArrays.StructArray{<: VecTypes{N}}, space = :data) where N | |
backing_arrays = getproperty.((structarray,), 1:N) | |
for i in 1:length(structarray) | |
transformed_point = Makie.apply_transform(f, structarray[i], :data) | |
for j in 1:N | |
backing_arrays[j][i] = transformed_point[j] | |
end | |
end | |
return structarray | |
end | |
function apply_transform!(fs::Tuple{<: Function, <: Function}, structarray::StructArrays.StructArray{<: VecTypes{N}}, space = :data) where N | |
backing_arrays = getproperty.((structarray,), 1:N) | |
backing_arrays[1][:] .= (fs[1]).(backing_arrays[1]) | |
backing_arrays[2][:] .= (fs[2]).(backing_arrays[2]) | |
return structarray | |
end | |
function Makie.plot!(plot::MeshImage) | |
points_observable = Observable{StructArrays.StructArray{Point2{Float64}, 1}}() | |
faces_observable = Observable{Vector{Makie.GLTriangleFace}}()#=GeometryBasics.QuadFace{Int}=# | |
uv_observable = Observable{Vector{Vec2f}}() | |
# lift(plot.npoints; ignore_equal_values = true, priority = 100) do npoints | |
# # could try GLTriangleFace, but that might not turn out well | |
# uv = map(x-> Vec2f(1f0 - x[2], 1f0 - x[1]), decompose_uv(rect)) | |
# uvm = GeometryBasics.Mesh(GeometryBasics.meta(ps; uv=uv), faces) | |
# return GeometryBasics.normal_mesh(uvm) | |
# end | |
old_npoints = typemin(Int)#plot.npoints[] | |
# handle the transformation | |
lift(plot[1], plot[2], plot.transformation.transform_func, plot.npoints, plot.space; ignore_equal_values = true) do x_in, y_in, tfunc, npoints, space | |
@show tfunc | |
if npoints != old_npoints | |
points_observable.val = StructArrays.StructArray{Point2{Float64}}(undef, npoints^2) | |
rect = GeometryBasics.Tesselation(Rect2f(0, 0, 1, 1), (npoints, npoints)) | |
faces_observable[] = GeometryBasics.decompose( | |
Makie.GLTriangleFace,#GeometryBasics.QuadFace{Int}, | |
rect | |
) | |
uv_observable[] = map(x-> Vec2f(1f0 - x[2], 1f0 - x[1]), GeometryBasics.decompose_uv(rect)) | |
end | |
xs = LinRange(extrema(x_in)..., npoints) | |
ys = LinRange(extrema(y_in)..., npoints) | |
poval = points_observable.val | |
pox = getproperty(poval, 1) | |
poy = getproperty(poval, 2) | |
# NOTE collect(tuple.(1:2, (1:2)'))[:] works fine | |
for (linear_ind, cartesian_ind) in enumerate(CartesianIndices((npoints, npoints))) | |
pox[linear_ind] = xs[cartesian_ind[1]] | |
poy[linear_ind] = ys[cartesian_ind[2]] | |
end | |
# apply the transformation to all points | |
# you can override this function to make it effective | |
# eg if transformation is known, | |
# OR is linearly separable, | |
# OR has a convenient C-api to transform arrays in place. | |
space === :data && apply_transform!(tfunc, poval, :data) | |
notify(points_observable) | |
if npoints != old_npoints | |
notify(faces_observable) | |
old_npoints = npoints | |
end | |
end | |
final_mesh = lift(points_observable, faces_observable, uv_observable; ignore_equal_values = true#=, priority = -100=#) do points, faces, uv | |
return GeometryBasics.normal_mesh(GeometryBasics.Mesh(GeometryBasics.meta(points; uv=uv), faces)) | |
end | |
mesh!(plot, final_mesh; color = plot[3], space = :transformed, shading = false) | |
end | |
function Makie.data_limits(plot::MeshImage) | |
mini_maxi = Makie.extrema_nan.((plot[1][], plot[2][])) | |
mini = Vec3f(first.(mini_maxi)..., 0) | |
maxi = Vec3f(last.(mini_maxi)..., 0) | |
return Rect3f(mini, maxi .- mini) | |
end |
Author
asinghvi17
commented
Mar 14, 2023
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment