Generative art · Independent project
MathRender
From a mathematical idea to art for my office.
Art for a particular room
I wanted artwork for my office, so I built a studio for making it from mathematics. The room gave me a concrete brief: work that would sit comfortably against walnut slats, with a palette, scale, and arrangement that belonged there.
The local application, FORM, lets me explore an equation, develop related variations, compose a collection against a photograph of the room, and prepare the files and measurements for printing and hanging. A saved recipe connects those steps.
The equation makes the form
The studio includes 30 mathematical systems across chaos, curves, knots, fields, and fractals. Each needs an appropriate numerical representation: a sampled trajectory, a set of paths, a point-density image, or a field evaluated on a grid.
For the Lorenz piece, SciPy integrates three coupled differential equations. Standard quality uses RK45; the higher settings use DOP853 with tighter tolerances. I keep the solver samples independent of print resolution, so changing the paper size does not silently change the trajectory.
dx/dt = σ(y − x)
dy/dt = x(ρ − z) − y
dz/dt = xy − βz- Paths and points
- Lorenz and other ODEs produce trajectories. Clifford and De Jong use simultaneous updates from the previous state; their images show where the resulting points accumulate.
- Curves and fields
- Parametric knots and spirals become paths. Chladni patterns and interference fields produce contours or raster images. Newton basins use iterative root finding to color regions of the plane.
- Numerical boundaries
- The engine checks nonfinite values and divergent solutions. Invalid spans are split into separate paths, keeping a discontinuity from becoming an accidental line across the artwork.
Explore a family of possibilities
Adjusting one slider at a time was too narrow a way to search for a piece. I built an explorer that renders twelve related studies, lets me favorite the promising ones, and uses those selections as parents for another round. Gentle, Balanced, and Bold control the amount of change.
Each child is an independent recipe with a deterministic seed. The generator cycles through the chosen parents and applies bounded changes. For the built-in chaotic ODEs, it preserves the equation coefficients and integration budgets while varying initial conditions and presentation. Colors, typography, and print settings stay together as a series.
The interface renders two previews at a time, keeps the history of each round, and shows failures on the affected card. Closing the explorer cancels unfinished work; choosing a favorite only changes the main composition when I select “Use in studio.”
Compose the print, then inspect it
The studio separates the mathematical form from its presentation. I can change the projection, rotation, crop, line weight, inks, border, and lettering while keeping the underlying recipe. Paper dimensions and margins are part of the composition from the start.
Inspection zoom changes only the view on screen. Artwork scale changes the printed composition. Keeping those controls separate matters when a pleasing thumbnail still needs to work at its intended size.
For three-dimensional forms, a projection set creates XY, XZ, and YZ studies from the same equation, parameters, and seed. It is a way to develop a coordinated collection by changing the viewpoint.
Design for the wall it will live on
I brought a photograph of the office into the planner so I could judge the work alongside the wood, paint, furniture, and lighting. Collections can share inks and typography while mixing portrait, landscape, and square formats.
The planner works in inches or centimeters. Prints have real paper and frame dimensions, can snap to a grid or align to one another, and report overlaps and gaps. Each item is a recipe snapshot, so editing the original study does not unexpectedly change a print already in the collection.
The room photograph is calibrated to the 48-inch slat-panel width. Its vertical placement is approximate; the hanging plan uses the explicit wall and frame measurements. That separates visual judgment in the photograph from the dimensions needed to hang the work.
Keep the detail at print size
The export path renders the recipe again at the requested physical size and PPI. A 36 × 24-inch Lorenz print at 300 PPI becomes 10,800 × 7,200 pixels. Its fine linework needs a different inspection standard from a browser preview.
A small proof uses the full-page transform and physical line widths, then crops a chosen region at the final PPI. The three-inch proof shown below is 900 × 900 pixels. It lets me inspect a manageable part of a large print without scaling down its detail.
PNG and TIFF exports carry an sRGB profile. SVG and PDF preserve compatible line and contour geometry as vectors; density, field, and basin artwork uses raster content where needed. Type is outlined in vector exports for portability, with the editable text retained in the recipe.
A collection export packages artwork files with recipes, print notes, a size-and-quantity manifest, and hanging plans. The current workflow produces RGB artwork; printer-specific soft proofing and CMYK conversion remain outside the app.
A local rendering system that stays usable
React and TypeScript handle the studio, variation explorer, and wall planner, with Vite for development and bundling. A local FastAPI service validates recipes and runs the numerical and rendering work in Python. NumPy and SciPy generate the forms; Matplotlib and Pillow turn them into previews, proofs, and exports.
The difficult part is keeping iteration responsive while supporting large files. A geometry cache is keyed by the mathematical definition, parameters, custom expressions, seed, and cache version. Camera, color, typography, and PPI are separate, so a finish change can reuse the mathematical work.
- Preview and final
- Previews cap their long edge at 1,400 pixels. Final exports reuse stored paths, but rebuild density bins and evaluate scalar or Newton grids at output resolution. A print is rendered from its recipe, not enlarged from the preview.
- Cancelable workers
- At most two child processes run concurrently, with only one full export at a time to leave capacity for preview work. Cancellation terminates active work, and time limits stop long-running requests. Estimated-memory checks screen large raster exports before they run. Collection files render one at a time.
- An expression language
- The custom-function editor parses an allowlisted arithmetic syntax tree. It supports named variables and mathematical functions, with limits on depth, operations, and exponents. Attribute access, indexing, imports, and arbitrary Python execution are excluded.
- Recoverable studies
- Browser storage keeps studies, variation history, and wall arrangements. JSON recipes make them portable. An active print-collection export can be recovered after a browser reload while the server remains running; render jobs do not survive a server restart.
Recipe
Validate the equation, parameters, seed, composition, and print settings. Keep a versioned JSON copy.
Geometry
Solve or sample the form, cache the result, and apply the chosen projection and composition.
Output
Render a preview, an actual-scale crop, or the final file using the requested physical dimensions.
Chaotic trajectories depend on solver settings and numerical-library versions. Recipes and locked dependencies preserve the configuration; identical pixels across different library versions are not promised.