# Conceptual problem with user recipes: draw a sphere before drawing the data

I am trying to do a user recipe from RecipesBase.jl but I seem to not get the idea how Recipes work I fear.

Context.
I would like to do something that I thought was quite easy. Given the `M=Sphere(2)` from Manifolds.jl and a set of points (maybe just `pts=[ [ 1.0, 0.0, 0.0], [0.0, 1.0, 0.0] ]` I would like to be able to write

`scene = plot(M,pts)`
to draw a sphere and two markers where these points are,
Best would be that for the scene I could also add things using `plot!(scene, M, pts2)` for a second set of points.

Here’s my current approach – and I can’t find what I am doing wrong, I fear I have a conceptual problem with recipes still.

Here’s my current (nonworking) MWE

``````using Manifolds, Plots, RecipesBase

@recipe function f(
M::Sphere{2},
pts::AbstractVector{T};
wireframe_lat=33,
wireframe_lon=33,
) where {T}
show_axis --> false
φ_range = range(0,stop=2*π,length=wireframe_lon)
λ_range = range(0,stop=π,length=wireframe_lat)
x = [cos(φ) * sin(λ) for φ ∈ φ_range, λ ∈ λ_range]
y = [sin(φ) * sin(λ) for φ ∈ φ_range, λ ∈ λ_range]
z = [cos(λ) for φ ∈ φ_range, λ ∈ λ_range]
scene = plot() # I assume this should be the global plot? Wherefrom?
wireframe!(scene, x, y, z)
seriestype --> :scatter
return [p for p ∈ pts], [p for p ∈ pts], [p for p ∈ pts]
end

M = Sphere(2)
pts = [ [1.0, 0.0, 0.0], [0.0, 1.0, 0.0] ]
plot(M, pts)
``````

and I also was not able to find something similar on the net.

How do I add something to a plot, when usually the recipe only returns `x, y, z` and I can’t seem to access the plot to add the sphere? It just plots the two points.

After a very quick glance at your code, I think you have a problem in the line with the following:

``````y = [sin(lon) * sin(lat) for φ ∈ φ_range, λ ∈ λ_range]
``````

`lon` and `lat` are not defined.

1 Like

Thanks for noticing, sorry, I copied an old version – name them `φ` and `λ` and it works, the plot actually has both points in, just no sphere

I also edited the original post.

I found one trick that seems to be a step forward – ` @series` from

but I can’t do a surface with that as I would do with `surface(x,y,z)` below

using Manifolds, Plots, RecipesBase

``````@recipe function f(
M::Sphere{2},
pts::AbstractVector{T};
wireframe_lat=33,
wireframe_lon=33,
) where {T}
show_axis --> false
φ_range = range(0,stop=2*π,length=wireframe_lon)
λ_range = range(0,stop=π,length=wireframe_lat)
x = [cos(φ) * sin(λ) for φ ∈ φ_range, λ ∈ λ_range]
y = [sin(φ) * sin(λ) for φ ∈ φ_range, λ ∈ λ_range]
z = [cos(λ) for φ ∈ φ_range, λ ∈ λ_range]
@series begin
# seriestype := :surface # this line does not work if you provide a surfce as set of points?
x,y,z #plots a line per z value not a surface
end
seriestype --> :scatter
return [p for p ∈ pts], [p for p ∈ pts], [p for p ∈ pts]
end

M = Sphere(2)
pts = [ [1.0, 0.0, 0.0], [0.0, 1.0, 0.0] ]
plot(M, pts)
``````

what I would like the `@series` is something either similar to `wireframe` or `surface` (in the end I want to be able to activate one, the other or both).

Edit: Ah, I see, so what I would like to obtain is what Make(!) does when you call `surface(x,y,z). on those data generated above, I.e. a nice surface of the sphere. How can I do that in Plots? And don’t recipes also work for Make? But they are still so different?

So my main problem seems to be that the series can not be convinced to do a 3D sphere (half transparent as a surface or as a mesh, either would be fine – later I want to be able to activate one of those or both). The result could vor example be similar to the plots I do with exports and rendering (Asymptote) here.

So how can I get a surface sphere in a series here ? Neither `:surface` nor `:wireframe` as `series type`do work.

I found the culprit: Ith works with `plotly()` as backend but not with `gr()`.

edit: I opened an Issue here at Plots.jl.

1 Like