#!/usr/bin/env python3 """bazaar.abaj.ai orb — milky-marble ground, golden dynamical-system flow, matte shading. Family style of the sibling icons (matplotlib figure clipped to a circle, 612pt). A damped two-vortex flow is integrated by hand (RK4) so line density stays airy; trajectories are drawn as tapering gold strokes over marble veining, then a radial matte falloff turns the disc into an orb. """ import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.collections import LineCollection from matplotlib.colors import LinearSegmentedColormap, to_rgb rng = np.random.default_rng(7) IVORY = '#fdfbf4' GOLDS = ['#8a6a08', '#a67c00', '#b8860b', '#c9a227', '#d4af37', '#e0c268'] # ── marble ground: domain-warped fBm veins ───────────────────────────────── N = 900 lin = np.linspace(-3, 3, N) X, Y = np.meshgrid(lin, lin) def fbm(x, y, octaves=5, seed=0): r = np.random.default_rng(seed) v = np.zeros_like(x) amp, freq = 1.0, 0.55 for _ in range(octaves): px, py = r.uniform(0, 100, 2) v += amp * np.sin(freq * (x + px) + 1.7 * np.cos(freq * (y + py))) v += amp * np.cos(freq * (y + py) - 1.3 * np.sin(freq * (x + px) * 0.7)) amp *= 0.55 freq *= 1.9 return v warp = fbm(X, Y, 4, seed=11) veins = fbm(X + 0.4 * warp, Y + 0.4 * warp, 5, seed=23) marble = np.abs(np.sin(1.1 * veins)) marble_cmap = LinearSegmentedColormap.from_list( 'marble', [(0.0, '#ece2cc'), (0.45, '#f8f4e8'), (0.8, '#ffffff'), (1.0, '#efe6d2')] ) # ── the dynamical system: spiral sink + off-centre secondary vortex ──────── def flow(x, y): # primary: gentle spiral sink at origin (no limit cycle → no pile-up) u = -y - 0.16 * x v = x - 0.16 * y # secondary influence: soft vortex up-right dx, dy = x - 1.15, y - 0.85 d2 = dx * dx + dy * dy + 0.4 u += 0.9 * dy / d2 v += -0.9 * dx / d2 return u, v def rk4_path(p, h=0.02, steps=340): pts = [p] x, y = p for _ in range(steps): k1 = flow(x, y) k2 = flow(x + h / 2 * k1[0], y + h / 2 * k1[1]) k3 = flow(x + h / 2 * k2[0], y + h / 2 * k2[1]) k4 = flow(x + h * k3[0], y + h * k3[1]) x += h / 6 * (k1[0] + 2 * k2[0] + 2 * k3[0] + k4[0]) y += h / 6 * (k1[1] + 2 * k2[1] + 2 * k3[1] + k4[1]) pts.append((x, y)) if x * x + y * y < 0.004: break return np.array(pts) # ── figure ───────────────────────────────────────────────────────────────── fig = plt.figure(figsize=(8.5, 8.5), dpi=72) # 612pt like the siblings ax = fig.add_axes([0, 0, 1, 1]) ax.set_xlim(-3, 3) ax.set_ylim(-3, 3) ax.set_aspect('equal') ax.axis('off') def clipped(artist): artist.set_clip_path(plt.Circle((0, 0), 3.0, transform=ax.transData)) return artist # marble ground clipped(ax.imshow(marble, extent=[-3, 3, -3, 3], cmap=marble_cmap, origin='lower', interpolation='bilinear', zorder=0)) # faint gold veining on the strongest ridges vein = np.where(marble > 0.88, marble, np.nan) clipped(ax.imshow(vein, extent=[-3, 3, -3, 3], origin='lower', cmap=LinearSegmentedColormap.from_list('gv', ['#00000000', '#b8860b30']), interpolation='bilinear', zorder=1)) # ── golden trajectories: two rings of seeds + a few strays ───────────────── seeds = [] for r, n, jit in [(2.85, 26, 0.05), (2.1, 14, 0.12)]: for th in np.linspace(0, 2 * np.pi, n, endpoint=False): th2 = th + rng.uniform(-jit, jit) seeds.append((r * np.cos(th2), r * np.sin(th2))) seeds += [(rng.uniform(-1.6, 1.9), rng.uniform(-1.6, 1.9)) for _ in range(8)] gold_cmap = LinearSegmentedColormap.from_list('golds', GOLDS) for i, s in enumerate(seeds): path = rk4_path(s, steps=rng.integers(220, 400)) if len(path) < 8: continue segs = np.stack([path[:-1], path[1:]], axis=1) t = np.linspace(0, 1, len(segs)) # 0 = tail, 1 = head base = to_rgb(gold_cmap(rng.uniform(0.15, 0.95))) colors = np.zeros((len(segs), 4)) colors[:, :3] = base colors[:, 3] = 0.16 + 0.6 * t**1.3 # fade in toward the sink lc = LineCollection(segs, colors=colors, linewidths=0.5 + 1.5 * t**1.6, # taper thin → full capstyle='round', zorder=3) clipped(ax.add_collection(lc)) # centre: the site's curved-diamond ✦ where all influence collects from matplotlib.path import Path as MPath from matplotlib.patches import PathPatch def curved_diamond(cx, cy, r, waist=0.30): """Four-pointed star with concave bezier edges (the ✦ mark).""" tips = [(cx, cy + r), (cx + r, cy), (cx, cy - r), (cx - r, cy)] verts, codes = [tips[0]], [MPath.MOVETO] for i in range(4): a, b = tips[i], tips[(i + 1) % 4] mx, my = (a[0] + b[0]) / 2, (a[1] + b[1]) / 2 ctrl = (cx + (mx - cx) * waist, cy + (my - cy) * waist) # pulled to centre verts += [ctrl, b] codes += [MPath.CURVE3, MPath.CURVE3] return MPath(verts, codes) star = curved_diamond(0.0, 0.0, 0.34) ax.add_patch(PathPatch(star, fc='#b8860b', ec='#8a6a08', lw=0.8, zorder=4, joinstyle='round')) # ── matte orb shading: limb darkening + broad milky key, no gloss ────────── rr = np.clip(np.sqrt(X**2 + Y**2) / 3.0, 0, 1) shade = np.clip(np.sqrt(1 - rr**2) ** 0.6, 0, 1) # 1 centre → 0 rim key = np.exp(-(((X + 1.35) ** 2 + (Y - 1.5) ** 2) / 7.0)) dark = np.zeros((N, N, 4)) dark[..., 0:3] = np.array([0.20, 0.16, 0.09]) dark[..., 3] = (1 - shade) ** 1.15 * 0.62 clipped(ax.imshow(dark, extent=[-3, 3, -3, 3], origin='lower', interpolation='bilinear', zorder=5)) milk = np.zeros((N, N, 4)) milk[..., 0:3] = 1.0 milk[..., 3] = key * shade * 0.38 clipped(ax.imshow(milk, extent=[-3, 3, -3, 3], origin='lower', interpolation='bilinear', zorder=6)) # hairline gold rim ax.add_patch(plt.Circle((0, 0), 2.985, fill=False, ec='#a67c00', lw=1.6, alpha=0.9, zorder=7)) fig.savefig('icon.svg', transparent=True) fig.savefig('preview.png', transparent=True, dpi=150) print('wrote icon.svg + preview.png')