## Orbit Diagram

```using Makie
using Observables

growth(🐇, 🥕) = 🐇 * 🥕 * (1.0 - 🐇)
function orbitdiagram(growth, r1, r2, n = 500, a = zeros(1000, n); T = 1000)
rs = range(r1, stop = r2, length = 1000)
for (j, r) in enumerate(rs)
x = 0.5
for _ in 1:T; x = growth(x, r); end
for i in 1:n
x = growth(x, r)
@inbounds a[j, i] = x
end
end
rs, a
end
r1 = slider(0:0.001:4, raw = true, camera=campixel!, start = 0.0)
r2 = slider(0:0.001:4, raw = true, camera=campixel!, start = 4)
n1 = 500; n2 = 1000; a = zeros(n2, n1)
positions = Vector{Point2f0}(undef, n1 * n2)
r1node, r2node = r1[end][:value], r2[end][:value]
r1r2 = async_latest(lift(tuple, r1node, r2node))
pos = lift(r1r2) do (r1, r2,)
global a
rs, a = orbitdiagram(growth, r1, r2, size(a, 2), a)
dim = size(a, 2)
for (i, r) in enumerate(rs)
positions[((i-1)*dim) + 1 : (i*dim)] .= Point2f0.(r, view(a, i, :))
end
positions
end
p = scatter(
pos, markersize = 0.006, color = (:black, 0.2),
show_axis = false
)
onany(pos) do pos
# faster to give the boundingbox ourselves, since otherwise we'll need to
# loop over pos!
#AbstractPlotting.update_limits!(p) # <- would calculate bb
AbstractPlotting.update_limits!(p, FRect(r1node[], 0, r2node[] - r1node[], 1))
AbstractPlotting.update!(p)
end
scene = hbox(
p,
vbox(r1, r2)
)
RecordEvents(scene, "output")

```