Friday, June 19, 2026

x̄ - > Generative Art: Five Mathematical Visualizations using python

Generative Art: Five Mathematical Visualizations

🎨 Generative Art: Five Mathematical Visualizations

Mathematical functions, when rendered visually, reveal stunning hidden geometry. From 3D wave-driven bar fields to psychedelic interference grids, these five plots demonstrate how pure equations can produce compelling art.

Each subplot below is generated entirely from NumPy and Matplotlib — no external data, just mathematics.

Key Idea: Every visual pattern here emerges from trigonometric functions, meshgrids, and carefully tuned color mappings — no artistic hand-drawing involved.

πŸ”’ The Five Charts at a Glance

The full figure is a 1 × 5 subplot layout rendered at 20 × 8 inches. Each panel targets a different mathematical structure:

# Chart Name Core Math Colormap
1 3D Bar Chart 3 + 2sin(2.2u) + 2cos(2.8v) cool
2 Radial Vortex Spiral: ΞΈ + 1.5r plasma
3 Color-Interference sin(2x² + 2y²)·cos(2xy) Custom psychedelic
4 Isosurface Contours sin(1.5X)cos(1.5Y) + sin(0.5X)sin(0.8Y) gist_earth
5 Noise Topography Fractal Brownian motion mimic Black contour lines
Read More

πŸ“Š 1. 3D Patterned Bar Chart

A 15 × 15 grid of bars is generated using a meshgrid, then heights are computed from a wave equation: top = 3 + 2sin(2.2u) + 2cos(2.8v), where u and v are normalized coordinates centered at the grid. Bar colors map height values through the cool colormap, creating a smooth cyan-to-magenta gradient.

Technique: ax.bar3d() with shade=True and per-bar color array derived from plt.cm.cool(top / max(top)).

πŸŒ€ 2. Radial Vortex

Twenty concentric rings (radii 0.1 → 0.9) are subdivided into 60 angular steps. Each step spawns a rotated Rectangle patch with spiral distortion applied as ΞΈ' = ΞΈ + 1.5r. Width scales as 0.06(1.1 - r) and height as 0.015r, making inner rectangles wider and outer ones taller, reinforcing the vortex depth illusion.

Key Detail: Rectangle orientation uses angle=degrees(ΞΈ') + 45, giving each tile an angled tilt that drives the swirling effect.

πŸ”¬ 3. Color-Interference Grid

A 40 × 40 grid of Circle patches is drawn over a black background. Each circle's radius and color are driven by the interference value val = sin(2x² + 2y²) · cos(2xy), normalized to [0, 1]. A custom colormap transitions through #00F0FF → #FF007F → #FFAA00 (cyan, magenta, amber), producing a vivid psychedelic moirΓ©.

πŸ”️ 4. Isosurface Contours

A surface is computed over a 100 × 100 meshgrid on [-3, 3]^2 using layered sine/cosine: Z = sin(1.5X)cos(1.5Y) + sin(0.5X)sin(0.8Y). The plot_surface call uses stride 3 with alpha 0.8 and the gist_earth colormap, while ax.contour() projects level curves onto the floor at z_{min} - 0.5.

Surface + Floor Contours

Isosurface preview

Full 5-Panel Layout

Full chart preview

πŸ—Ί️ 5. Perlin Noise Topography

The final panel mimics fractal Brownian motion over a 150 × 150 grid on [-5, 5]^2 using three octaves:

  • Octave 1 (amplitude 1.0): sin(X)cos(Y)
  • Octave 2 (amplitude 0.5): sin(2X)sin(2Y)
  • Octave 3 (amplitude 0.25): cos(4X)cos(4Y)

The result is plotted as 18 black contour lines (linewidths=1.2) on a white background, evoking a topographic survey map with clean, high-contrast readability.

Fractal Property: Each successive octave doubles the spatial frequency and halves the amplitude — a direct analogue to the standard fBm construction used in Perlin noise.

⚙️ Reproduction Code

The full figure is assembled with a single plt.figure(figsize=(20, 8)) call. Run the snippet below to reproduce all five panels:

Dependencies: numpy, matplotlib (including mpl_toolkits.mplot3d). No external datasets required.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle, Circle
from matplotlib.colors import LinearSegmentedColormap
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(20, 8), facecolor="white")

# --- 1. 3D Bar Chart ---
ax1 = fig.add_subplot(1, 5, 1, projection='3d')
_x = np.arange(15); _y = np.arange(15)
X, Y = np.meshgrid(_x, _y)
x, y = X.ravel(), Y.ravel()
u = (x - 7.5) / 5.0; v = (y - 7.5) / 5.0
top = 3 + 2 * np.sin(2.2 * u) + 2 * np.cos(2.8 * v)
ax1.bar3d(x, y, np.zeros_like(top), 0.7, 0.7, top,
          shade=True, color=plt.cm.cool(top / np.max(top)))
ax1.set_title("3D Bar Chart", fontsize=12, pad=10); ax1.axis('off')

# --- 2. Radial Vortex ---
ax2 = fig.add_subplot(1, 5, 2)
ax2.set_aspect('equal'); ax2.set_facecolor('white')
for r in np.linspace(0.1, 0.9, 20):
    for theta in np.linspace(0, 2*np.pi, 60):
        ct = theta + 1.5 * r
        rect = Rectangle(
            (r*np.cos(ct) - 0.03*(1.1-r), r*np.sin(ct) - 0.0075*r),
            0.06*(1.1-r), 0.015*r,
            angle=np.degrees(ct)+45,
            facecolor=plt.cm.plasma(r), edgecolor='none')
        ax2.add_patch(rect)
ax2.set_xlim(-1,1); ax2.set_ylim(-1,1)
ax2.set_title("Radial Vortex", fontsize=12, pad=10); ax2.axis('off')

# --- 3. Color-Interference ---
ax3 = fig.add_subplot(1, 5, 3)
ax3.set_aspect('equal'); ax3.set_facecolor('black')
cmap = LinearSegmentedColormap.from_list("psych",["#00F0FF","#FF007F","#FFAA00"])
for x in np.linspace(-2, 2, 40):
    for y in np.linspace(-2, 2, 40):
        val = (np.sin(2*x**2+2*y**2)*np.cos(2*x*y)+1)/2
        ax3.add_patch(Circle((x,y), 0.04*val+0.01,
                             facecolor=cmap(val), edgecolor='none'))
ax3.set_xlim(-2.2,2.2); ax3.set_ylim(-2.2,2.2)
ax3.set_title("Color-Interference", fontsize=12, pad=10); ax3.axis('off')

# --- 4. Isosurface Contours ---
ax4 = fig.add_subplot(1, 5, 4, projection='3d')
X,Y = np.meshgrid(np.linspace(-3,3,100), np.linspace(-3,3,100))
Z = np.sin(X*1.5)*np.cos(Y*1.5) + np.sin(X*0.5)*np.sin(Y*0.8)
ax4.plot_surface(X,Y,Z,rstride=3,cstride=3,cmap='gist_earth',alpha=0.8,edgecolor='none')
ax4.contour(X,Y,Z,zdir='z',offset=Z.min()-0.5,cmap='gist_earth',linewidths=0.8)
ax4.set_zlim(Z.min()-0.5, Z.max()+0.5)
ax4.set_title("Isosurface Contours", fontsize=12, pad=10); ax4.axis('off')

# --- 5. Noise Topography ---
ax5 = fig.add_subplot(1, 5, 5)
ax5.set_aspect('equal')
X,Y = np.meshgrid(np.linspace(-5,5,150), np.linspace(-5,5,150))
Z = (np.sin(X)*np.cos(Y) + 0.5*np.sin(2*X)*np.sin(2*Y)
     + 0.25*np.cos(4*X)*np.cos(4*Y))
ax5.contour(X,Y,Z,levels=18,colors='black',linewidths=1.2)
ax5.set_title("Noise Topography", fontsize=12, pad=10); ax5.axis('off')

plt.tight_layout()
plt.savefig("generative_art.png", dpi=150, bbox_inches='tight')
plt.show()
  

⏭️ Next Steps

Future extensions could replace the fBm mimic with true Perlin or Simplex noise via the noise library, animate the vortex and interference panels using FuncAnimation, or export each subplot as an individual SVG for web embedding.

No comments:

Meet the Authors
Zacharia Maganga’s blog features multiple contributors with clear activity status.
Active ✔
πŸ§‘‍πŸ’»
Zacharia Maganga
Lead Author
Active ✔
πŸ‘©‍πŸ’»
Linda Bahati
Co‑Author
Active ✔
πŸ‘¨‍πŸ’»
Jefferson Mwangolo
Co‑Author
Inactive ✖
πŸ‘©‍πŸŽ“
Florence Wavinya
Guest Author
Inactive ✖
πŸ‘©‍πŸŽ“
Esther Njeri
Guest Author
Inactive ✖
πŸ‘©‍πŸŽ“
Clemence Mwangolo
Guest Author

Followers

Support This Blog
Tap Donate now here to donate or go to donate on top menu to scan QR and support this site.
Donate Now