Skip to content

ComplexPlot3D ​

<ComplexPlot3D value="1/(z^2 + 1)"> -- Wolfram's ComplexPlot3D: |f(z)| as a surface over the complex plane, each face colored by arg f(z) on the same gradient <ComplexPlot> paints (gradient, default phase, the hue wheel; reverse turns it round). A pole is a spike that rises to max-height with every hue winding round it; a zero is a dimple the hues wind round the other way.

value is Epsil; LaTeX is accepted inside a $…$ island. Sampled in a WebGPU compute shader through the same complex lowering the portrait uses, falling back to the CPU -- the base package's complex evaluator, or the engine's own numeric evaluation for a head it has no lowering for -- where WebGPU is missing or the expression doesn't lower. gpu="false" forces the CPU; a number sets the GPU's samples. Drag rotates, ctrl/⌘ + wheel zooms, double-click resets the view.

A grid past CANVAS_THRESHOLD samples a side is painted on a canvas rather than serialised as SVG: the same projection and painter's order, but no DOM node per face, so a GPU-resolution surface still turns under the pointer.

The surface is cut at max-height rather than left to grow without bound near a pole, as Wolfram's is, so a single pole does not flatten everything else to the floor. A face's hue is the circular mean of its corners, so a cell straddling arg = ±π takes the hue between its sides rather than the opposite one.

packages/components/src/notatio-complex-plot-3d.ts· draws ComplexPlot3D

Stories

A rational function

Two poles at ±i, clipped at the ceiling, and the hue running once round each.

source
ComplexPlot3D(1 / (z ^ 2 + 1))

notebook cells, the CLI

Zeros too

The cube roots of unity are the three dimples; the poles are the two spikes. Reading the colour wheel round a point gives its order, and the direction of the winding says which.

source
ComplexPlot3D((z ^ 3 - 1) / (z ^ 2 + 1), (z, -2 - 2i, 2 + 2i), (Samples, 60))

notebook cells, the CLI

The gamma function

Poles at 0, −1, −2, …, each a spike; to the right the surface climbs as the factorials do.

source
ComplexPlot3D(Gamma(z), (z, -4 - 3i, 4 + 3i), (Samples, 60), (MaxHeight, 6))

notebook cells, the CLI

The Riemann zeta function

The pole at z = 1, and up the critical line the first non-trivial zeros at ½ + 14.13i, ½ + 21.02i, ½ + 25.01i -- the dimples every hue winds round.

source
ComplexPlot3D(Zeta(z), (z, -2, 3 + 30i), (Samples, 70), (MaxHeight, 3))

notebook cells, the CLI

A dense rational surface

The rational function again at 160 samples a side, so the spikes come to a point and the hue is continuous across each face.

source
ComplexPlot3D((z ^ 3 - 1) / (z ^ 2 + 1), (Gpu, 160), (MaxHeight, 3))

notebook cells, the CLI

An essential singularity

Exp(1/z) near the origin: the surface climbs to the ceiling on the right and falls to the floor on the left, and between them every hue passes infinitely often.

source
ComplexPlot3D(
               ExponentialE ^ (1 / z),
               (z, -1 - i, 1 + i),
               (Gpu, 200),
               (MaxHeight, 3),
               (Elevation, 30),
             )

notebook cells, the CLI

The trigamma function

PolyGamma(1, z) through the analytic kernels on the GPU: double poles at 0, −1, −2, …, so the hue winds twice round each spike.

source
ComplexPlot3D(PolyGamma(1, z), (z, -4 - 2i, 2 + 2i), (Gpu, 160), (MaxHeight, 5))

notebook cells, the CLI

Through an expression, corner-to-corner

The head is the component: an evaluated ComplexPlot3D(f, (z, a + b i, c + d i)) draws itself, the iterator's complex corners becoming the domain -- the same picture as the first story, written the other way.

source
ComplexPlot3D(1 / (z ^ 2 + 1), (z, -2 - 2i, 2 + 2i))

notebook cells, the CLI

The argument on the sinebow gradient

Faces take arg f(z) on the gradient; phase, the hue wheel, by default.

source
ComplexPlot3D(1 / (z ^ 2 + 1), (z, -2 - 2i, 2 + 2i), (ColorFunction, "Sinebow"))

notebook cells, the CLI

Props

PropTypeDefaultNotes
valuestring""The complex-valued expression to draw, in Epsil.
varstring"z"The complex variable; defaults to z.
domainstring"-2,2,-2,2"The rectangle to sample, as re0,re1,im0,im1.
samplesnumber40Samples per side, clamped to 2..400.
gpustring"""false" samples on the CPU even where WebGPU is available. A number sets samples for the GPU.
maxHeight
attribute max-height
number4Height ceiling for |f|, since a pole goes to infinity.
axesstring"true""false" hides the axes frame and its range labels.
azimuthnumber45Rotation about the vertical, in degrees. Dragging changes this.
elevationnumber25Viewing angle above the plane, in degrees. Dragging changes this.
zoomnumber1View scale; ctrl/cmd + wheel or a pinch changes this. Double-click resets.
labelstring""Caption drawn above the surface.
gradientstring"phase"The gradient the argument is colored with: phase (the hue wheel, the default), sinebow, turbo, ….
reversebooleanfalseRun the gradient from its last color to its first.

As a web component

Plain custom elements, no framework required: import @enumeratio/frontend for the side effect and write <notatio-complex-plot-3d> in any HTML. Attributes are kebab-case and always strings; the props table above names each one's attribute where it differs from its prop.

Settable only as a JS property, not an attribute -- bindings: bind with :bindings.prop="…" directly on the tag.