{"spec_id":"wireframe-3d-basic","library":"makie","language":"julia","code":"# anyplot.ai\n# wireframe-3d-basic: Basic 3D Wireframe Plot\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 85/100 | Created: 2026-08-04\n\nusing CairoMakie\nusing Colors\n\n# --- Theme tokens -----------------------------------------------------------\nconst THEME    = get(ENV, \"ANYPLOT_THEME\", \"light\")\nconst PAGE_BG  = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nconst INK      = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\nconst ANYPLOT_SEQ = cgrad([colorant\"#009E73\", colorant\"#4467A3\"])  # sequential, height-encoded\n\n# --- Data ---------------------------------------------------------------\n# Ripple function z = sin(0.55 * r) / (r + 1) evaluated on a 20x20 grid.\n# The damped oscillation (~1.1 periods across the domain, vs. ~2.2 previously)\n# and coarser grid keep the mesh see-through instead of cluttered near the peak.\ngrid_points = range(-10, 10; length = 20)\nx = collect(grid_points)\ny = collect(grid_points)\nradius = [sqrt(xi^2 + yi^2) for xi in x, yi in y]\nz = sin.(0.55 .* radius) ./ (radius .+ 1)\n\n# --- Plot -----------------------------------------------------------------\ntitle_text = \"wireframe-3d-basic · julia · makie · anyplot.ai\"\ntitle_fontsize = round(Int, 20 * min(1.0, 67 / length(title_text)))\n\nfig = Figure(\n    resolution      = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis3(\n    fig[1, 1];\n    title             = title_text,\n    titlesize         = title_fontsize,\n    titlecolor        = INK,\n    xlabel            = \"X\",\n    ylabel            = \"Y\",\n    zlabel            = \"Z\",\n    xlabelsize        = 14,\n    ylabelsize        = 14,\n    zlabelsize        = 14,\n    xticklabelsize    = 12,\n    yticklabelsize    = 12,\n    zticklabelsize    = 12,\n    xlabelcolor       = INK,\n    ylabelcolor       = INK,\n    zlabelcolor       = INK,\n    xticklabelcolor   = INK_SOFT,\n    yticklabelcolor   = INK_SOFT,\n    zticklabelcolor   = 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    xzpanelcolor      = PAGE_BG,\n    yzpanelcolor      = PAGE_BG,\n    azimuth           = deg2rad(45 + 90),\n    elevation         = deg2rad(30),\n    aspect            = (1, 1, 0.6),\n)\n\n# Height-based line coloring (brand green -> blue via ANYPLOT_SEQ) so each\n# wireframe segment is colored by the endpoints' z-height, giving the mesh a\n# depth cue instead of a single flat line color.\ngrid_m, grid_n = size(z)\nline_faces = Makie.decompose(\n    Makie.LineFace{Makie.GLIndex}, Makie.Tesselation(Makie.Rect2(0, 0, 1, 1), (grid_m, grid_n))\n)\nz_per_vertex = vec(z)\nsegment_colors = Float64[]\nfor face in line_faces\n    push!(segment_colors, z_per_vertex[face[1]])\n    push!(segment_colors, z_per_vertex[face[2]])\nend\n\nwireframe!(\n    ax, x, y, z;\n    color = segment_colors, colormap = ANYPLOT_SEQ, colorrange = extrema(z), linewidth = 1.3,\n)\n\n# --- Save -------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}