{"spec_id":"line-3d-trajectory","library":"makie","language":"julia","code":"# anyplot.ai\n# line-3d-trajectory: 3D Line Plot for Trajectory Visualization\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 89/100 | Created: 2026-09-10\n\nusing CairoMakie\nusing Colors\n\n# --- Theme tokens -----------------------------------------------------------\nTHEME       = get(ENV, \"ANYPLOT_THEME\", \"light\")\nPAGE_BG     = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nELEVATED_BG = THEME == \"light\" ? colorant\"#FFFDF6\" : colorant\"#242420\"\nINK         = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nINK_SOFT    = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\n\nIMPRINT_PALETTE = [\n    colorant\"#009E73\", colorant\"#C475FD\", colorant\"#4467A3\", colorant\"#BD8233\",\n    colorant\"#AE3030\", colorant\"#2ABCCD\", colorant\"#954477\", colorant\"#99B314\",\n]\nANYPLOT_SEQ = cgrad([colorant\"#009E73\", colorant\"#4467A3\"])  # sequential — time progression\n\n# --- Data: Lorenz attractor trajectory (classic chaotic system) ------------\nsigma, rho, beta = 10.0, 28.0, 8.0 / 3.0\ndt = 0.014\nn_steps = 2000\n\nfunction integrate_lorenz(x0, y0, z0, n_steps, dt, sigma, rho, beta)\n    xs, ys, zs = zeros(n_steps), zeros(n_steps), zeros(n_steps)\n    xs[1], ys[1], zs[1] = x0, y0, z0\n\n    for i in 1:(n_steps - 1)\n        xi, yi, zi = xs[i], ys[i], zs[i]\n\n        k1x, k1y, k1z = sigma * (yi - xi), xi * (rho - zi) - yi, xi * yi - beta * zi\n        xa, ya, za = xi + 0.5dt * k1x, yi + 0.5dt * k1y, zi + 0.5dt * k1z\n\n        k2x, k2y, k2z = sigma * (ya - xa), xa * (rho - za) - ya, xa * ya - beta * za\n        xb, yb, zb = xi + 0.5dt * k2x, yi + 0.5dt * k2y, zi + 0.5dt * k2z\n\n        k3x, k3y, k3z = sigma * (yb - xb), xb * (rho - zb) - yb, xb * yb - beta * zb\n        xc, yc, zc = xi + dt * k3x, yi + dt * k3y, zi + dt * k3z\n\n        k4x, k4y, k4z = sigma * (yc - xc), xc * (rho - zc) - yc, xc * yc - beta * zc\n\n        xs[i + 1] = xi + (dt / 6) * (k1x + 2k2x + 2k3x + k4x)\n        ys[i + 1] = yi + (dt / 6) * (k1y + 2k2y + 2k3y + k4y)\n        zs[i + 1] = zi + (dt / 6) * (k1z + 2k2z + 2k3z + k4z)\n    end\n\n    return xs, ys, zs\nend\n\n# Two nearby initial conditions illustrate chaotic sensitivity: the paths\n# stay close for most of the run, then fork apart once the perturbation has\n# grown enough to be visible — the hallmark \"butterfly effect\" of this system.\ntraj_x, traj_y, traj_z = integrate_lorenz(0.1, 0.0, 0.0, n_steps, dt, sigma, rho, beta)\ntraj2_x, traj2_y, traj2_z = integrate_lorenz(0.1 + 1.0e-3, 0.0, 0.0, n_steps, dt, sigma, rho, beta)\n\nseparation = sqrt.((traj_x .- traj2_x) .^ 2 .+ (traj_y .- traj2_y) .^ 2 .+ (traj_z .- traj2_z) .^ 2)\nfork_idx = something(findfirst(d -> d > 2.0, separation), n_steps ÷ 2)\n\n# --- Plot ---------------------------------------------------------------\nfig = Figure(\n    size            = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis3(\n    fig[1, 1];\n    title              = \"line-3d-trajectory · julia · makie · anyplot.ai\",\n    titlesize          = 20,\n    titlecolor         = INK,\n    xlabel             = \"X\",\n    ylabel             = \"Y\",\n    zlabel             = \"Z\",\n    xlabelsize         = 14,\n    ylabelsize         = 14,\n    zlabelsize         = 14,\n    xlabelcolor        = INK,\n    ylabelcolor        = INK,\n    zlabelcolor        = INK,\n    xticklabelsize     = 12,\n    yticklabelsize     = 12,\n    zticklabelsize     = 12,\n    xticklabelcolor    = INK_SOFT,\n    yticklabelcolor    = INK_SOFT,\n    zticklabelcolor    = INK_SOFT,\n    xtickcolor         = INK_SOFT,\n    ytickcolor         = INK_SOFT,\n    ztickcolor         = INK_SOFT,\n    xgridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n    ygridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n    zgridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n    xspinecolor_1      = INK_SOFT,\n    yspinecolor_1      = INK_SOFT,\n    zspinecolor_1      = INK_SOFT,\n    xspinecolor_2      = INK_SOFT,\n    yspinecolor_2      = INK_SOFT,\n    zspinecolor_2      = INK_SOFT,\n    xspinecolor_3      = INK_SOFT,\n    yspinecolor_3      = INK_SOFT,\n    zspinecolor_3      = INK_SOFT,\n    xypanelcolor       = PAGE_BG,\n    yzpanelcolor       = PAGE_BG,\n    xzpanelcolor       = PAGE_BG,\n    backgroundcolor    = PAGE_BG,\n    aspect             = :data,\n    elevation          = 0.22 * pi,\n    azimuth            = -0.32 * pi,\n)\n\nlines!(ax, traj_x, traj_y, traj_z; color = 1:n_steps, colormap = ANYPLOT_SEQ, linewidth = 2.5, alpha = 0.9)\nscatter!(ax, [traj_x[1]], [traj_y[1]], [traj_z[1]]; color = IMPRINT_PALETTE[1], markersize = 16, strokewidth = 0)\n\n# The perturbed run shares the same path as the main trajectory up to\n# `fork_idx`; only the diverged tail is drawn, so the fork itself is the\n# visible story rather than two fully overlapping lines. A dashed style\n# (on top of the distinct lavender color) keeps the diverged path readable\n# even where it briefly re-overlaps the main spiral.\ntraj2_line = lines!(\n    ax, traj2_x[fork_idx:end], traj2_y[fork_idx:end], traj2_z[fork_idx:end];\n    color = IMPRINT_PALETTE[2], linewidth = 3.0, linestyle = :dash, alpha = 1.0,\n)\nscatter!(ax, [traj2_x[fork_idx]], [traj2_y[fork_idx]], [traj2_z[fork_idx]]; color = IMPRINT_PALETTE[2], markersize = 14, strokewidth = 0)\n\nColorbar(\n    fig[1, 2];\n    limits       = (0, n_steps * dt),\n    colormap     = ANYPLOT_SEQ,\n    label        = \"Time\",\n    labelsize    = 14,\n    labelcolor   = INK,\n    ticklabelsize = 12,\n    ticklabelcolor = INK_SOFT,\n    tickcolor    = INK_SOFT,\n    width        = 14,\n)\n\nLegend(\n    fig[2, 1:2],\n    [traj2_line],\n    [\"Diverged path from a perturbed initial condition (Δx₀ = 0.001)\"];\n    orientation     = :horizontal,\n    framevisible    = false,\n    backgroundcolor = :transparent,\n    labelcolor      = INK,\n    tellwidth       = false,\n    tellheight      = true,\n)\n\ncolsize!(fig.layout, 1, Relative(0.95))\nrowsize!(fig.layout, 1, Auto(1.0))\nrowsize!(fig.layout, 2, Fixed(70))\n\n# --- Save -----------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}