A saddle
source
<notatio-plot-3d value="x^2 - y^2" x-domain="-2,2" y-domain="-2,2" />A bivariate surface (Plot3D), rendered by <notatio-plot-3d>. It samples an n×n grid, projects it obliquely, and paints the quads back-to-front with height shading — pure SVG, no WebGL. value is notatio; LaTeX goes in a $…$ island. A boxed axes frame with range labels draws by default (axes="false" to hide); each axis takes x-scale / y-scale / z-scale.
The view is interactive: drag to rotate (azimuth / elevation, in degrees), ctrl/⌘ + wheel or a pinch to zoom (zoom), and double-click to reset to the initial view. Sampling happens once per expression; a view change only re-projects the cached grid. label adds a PlotLabel title, and color-legend a height key. Hover the surface to read out the nearest sample's (x, y, z). A list of expressions overlays several surfaces on one shared z-scale, each in its own colour. params adds Manipulate sliders — see Manipulate below. A spin toggle under each figure auto-rotates the view (spin starts it on), so a surface can turn hands-free. Set gpu (opt-in) to evaluate the grid in a WebGPU compute shader — see GPU evaluation.
<notatio-plot-3d value="x^2 - y^2" x-domain="-2,2" y-domain="-2,2" /><notatio-plot-3d value="Sin(x) * Cos(y)" x-domain="-3.14,3.14" y-domain="-3.14,3.14" />spin starts the view turning on load; toggle it with the ⟳ spin button, and drag to take over.
<notatio-plot-3d value="Sin(x) * Cos(y)" x-domain="-3.14,3.14" y-domain="-3.14,3.14" spin />label is a PlotLabel title; color-legend draws a height key matching the surface's shading. Hover to read a sample.
<notatio-plot-3d value="Exp(-(x^2 + y^2) / 4)" x-domain="-4,4" y-domain="-4,4" label="Gaussian" color-legend />The initial view is attribute-driven; drag to change it, then double-click to snap back here.
<notatio-plot-3d value="Sin(x) * Cos(y)" x-domain="-3.14,3.14" y-domain="-3.14,3.14" azimuth="200" elevation="40" zoom="0.8" /> A list of expressions draws several surfaces on one shared z-scale, each in its own colour. Two ripples offset in z stack as clean layers — the oblique painter's order sorts cells across both, so pick surfaces that don't intersect (an intersection can't be resolved without true 3-D clipping).
<notatio-plot-3d value="{Sin(x) * Cos(y) + 2.5, Cos(x) * Sin(y) - 2.5}" x-domain="-3.14,3.14" y-domain="-3.14,3.14" /><notatio-plot-3d value="x^2 - y^2" x-domain="-2,2" y-domain="-2,2" axes="false" />params binds Manipulate control tuples into the expression; each control fills the matching named wildcard (control k fills _k). Each slider gets a play button (▶) that animates it on a loop. Drag still rotates the view.
The slider fills _k and re-samples the whole grid; press ▶ to sweep it.
<notatio-plot-3d value="Sin(_k * x) * Cos(_k * y)" x-domain="-3.14,3.14" y-domain="-3.14,3.14" params="{k, 0.5, 3}" /> A blend parameter t in [0, 1] interpolates a saddle into a ripple. Press ▶ to watch it morph.
<notatio-plot-3d value="(1 - _t) * (x^2 - y^2) + _t * Sin(x) * Cos(y) * 4" x-domain="-2,2" y-domain="-2,2" params="{t, 0, 1}" /> Animating the phase p sends ripples outward from the origin.
<notatio-plot-3d value="Sin(2 * Sqrt(x^2 + y^2) - _p)" x-domain="-4,4" y-domain="-4,4" params="{p, 0, 6.283}" />Sampling is normally done on the CPU — the expression is compiled to a native function (so even Manipulate sliders stay smooth). Set gpu to instead evaluate the whole grid in a WebGPU compute shader: the expression compiles to WGSL through compute-engine's WGSL target (special-function heads like HurwitzZeta emit calls into the zetaWGSL kernel), one shader invocation per grid point. gpu="120" also sets a denser grid, since the GPU handles far more points; a GPU badge appears under the figure when the path is taken. It falls back to the CPU automatically where WebGPU is unavailable or the expression can't be compiled — so it is safe to leave on.
The grid (here 100×100) is computed in a compute shader, then drawn through the same SVG surface. Needs a WebGPU browser; otherwise it renders on the CPU.
<notatio-plot-3d value="Sin(x) * Cos(y)" x-domain="-3.14,3.14" y-domain="-3.14,3.14" gpu="100" />gpu); the remaining lift is a GPU scene renderer (the sibling's polytope-figure) for when the SVG mesh stops scaling.