Hello all, I’m currently facing a strange error while using a custom recipe. This error only showed up with recent versions of Makie, but I could not find the source.
Here is the problem, for meshscatters, Makie has only the :Sphere
option available, so I figured I could define my own addition and define several 3D marker shapes to pass to meshscatter
. However, I’d like to keep the capability to update this marker shape on the fly with an Observable
. This gives the following code
using GLMakie
function marker_geometry(marker_symbol::Symbol, marker_size::Real)
marker_size = Float64(marker_size)
if marker_symbol === :sphere
return Makie.Sphere(Makie.Point3(0.0), marker_size)
elseif marker_symbol === :cube
return Makie.Rect3(Makie.Vec3(-marker_size), Makie.Vec3(2 * marker_size))
elseif marker_symbol === :pyramid
return Makie.Pyramid(Makie.Point3(0.0, 0.0, marker_size / 2), marker_size, marker_size)
elseif marker_symbol === :cylinder
return Makie.Cylinder(Makie.Point3(0.0, 0.0, -marker_size), Makie.Point3(0.0, 0.0, marker_size), marker_size)
else
@warn "nodemarker must be either set to (:sphere, :cube, :pyramid, :cylinder), defaulting to :sphere"
return Makie.Sphere(Makie.Point3(0.0), marker_size)
end
end
Makie.@recipe(NodePlot, points) do scene
Attributes(
nodemarker=:sphere,
nodesize=1.0
)
end
function Makie.plot!(plt::NodePlot{<:Tuple{Any}})
# Unpack all relevant arguments
(; points, nodemarker, nodesize) = plt
# Actually draw the markers
marker = Observable{Any}()
lift(nodemarker, nodesize) do nodemarker, nodesize
# Define the marker object depending on the selected option
marker[] = marker_geometry(nodemarker, nodesize)
end
meshscatter!(plt, points, marker=marker)
return plt
end
If I try and plot this with
f,ax,p = nodeplot(rand(Point3,10))
p.nodemarker = :cube
I get the following error
ERROR: MethodError: Cannot `convert` an object of type Rect3{Float64} to an object of type Sphere{Float64}
Closest candidates are:
convert(::Type{T}, ::T) where T
@ Base Base.jl:84
(::Type{GeometryBasics.HyperSphere{N, T}} where {N, T})(::Any, ::Any)
so it looks like there is another observable in the background that is concretely typed and blocks me from updating the marker. The weird part is that Makie actually shows cubes regardless. Also directly passing a 3D shape to meshscatter
works fine, so it looks like it’s really in the recipe.
Can someone explain this behavior ?
EDIT Here is the stacktrace
Stacktrace:
[1] setproperty!(x::Observable{Sphere{Float64}}, f::Symbol, v::Rect3{Float64})
@ Base .\Base.jl:40
[2] setindex!(observable::Observable, val::Any)
@ Observables user\.julia\packages\Observables\YdEbO\src\Observables.jl:122
[3] (::Observables.MapCallback)(value::Any)
@ Observables user\.julia\packages\Observables\YdEbO\src\Observables.jl:436
[4] #invokelatest#2
@ Base .\essentials.jl:887 [inlined]
[5] invokelatest
@ Base .\essentials.jl:884 [inlined]
[6] notify
@ Observables user\.julia\packages\Observables\YdEbO\src\Observables.jl:206 [inlined]
[7] setindex!(observable::Observable, val::Any)
@ Observables user\.julia\packages\Observables\YdEbO\src\Observables.jl:123
[8] setindex!(x::Plot{nodeplot, Tuple{Vector{Point3}}}, value::Symbol, key::Symbol)
@ MakieCore user\.julia\packages\MakieCore\UAwps\src\attributes.jl:224
[9] setproperty!(x::Plot{nodeplot, Tuple{Vector{Point3}}}, key::Symbol, value::Symbol)
@ MakieCore user\.julia\packages\MakieCore\UAwps\src\attributes.jl:101