Two Suns Gravity Visualizer Visualizzatore gravitazionale a due soli
Two Suns Gravity Visualizer turns a simple gravitational experiment into generative art. Two suns are fixed on a plane. A test particle is released from rest at every pixel of an image, each trajectory is integrated forward, and the pixel receives the color of the sun that eventually captures its particle.
The result is a basin-of-attraction map: a global picture assembled from hundreds of thousands of independent initial-value problems. Smooth regions indicate nearby initial conditions with the same outcome, while intricate boundaries reveal places where a small displacement can change the winning sun. By moving the suns, changing the canvas proportions, and selecting a color palette, the browser app can generate high-resolution images suitable for wallpapers.
The physical model
Let the two fixed suns be at positions and , and let a unit-mass test particle have position . The simulation uses equal source masses and dimensionless pixel coordinates. Its acceleration is
This is the inverse-square law in vector form: the numerator points toward a sun, while division by the cube of the distance leaves an acceleration magnitude proportional to . The parameter combines the gravitational constant and source mass into one tunable strength.
Every image coordinate becomes an initial condition
The two primaries remain fixed and do not attract or orbit one another. The model is therefore a stylized fixed-center problem rather than a full physical three-body simulation. It is designed to expose geometric structure, not to predict an astronomical system.
Why the picture forms
For each starting pixel, the solver asks a binary question: does the trajectory first enter the capture disk around sun 1 or sun 2? All starting positions that produce the same answer form that sun’s basin of attraction.
Near a sun, the local pull is usually decisive. Between the suns and around the basin boundary, however, a particle can accelerate toward one center, overshoot it, swing through the competing field, and later be captured by the other. Neighboring pixels may therefore trace very different paths before receiving different colors. The final image records outcomes rather than drawing the trajectories themselves.
Pure point-mass gravity is singular at a sun’s exact position. The implementation softens the squared distances,
before evaluating . The default prevents division by zero and limits numerical overflow without visibly enlarging the suns.
Numerical integration
The second-order equation is represented as the first-order system
Each trajectory is advanced with semi-implicit Euler, also called symplectic Euler:
Updating position with the new velocity is the defining difference from forward Euler. It is inexpensive and is generally better behaved for Hamiltonian motion, making it a useful compromise when the same update must be applied to every pixel many hundreds of times.
The default Python renderer uses , , a capture radius of 3 pixels, and at most 800 steps. The browser version uses the same physical constants and capture radius with a 700-step limit. If a particle enters both capture disks in one step, the closer sun wins. If it never enters either disk before the limit, it is assigned to whichever sun is nearer at its final simulated position. This fallback guarantees that every output pixel receives a color, although it should be interpreted as a rendering rule rather than a demonstrated physical capture.
The parameters also reveal the numerical nature of the image. Larger time steps are faster but can skip across a small capture disk; smaller steps resolve close encounters better but increase render time. Capture radius and maximum steps change the classification near difficult trajectories. The generated boundary is therefore a property of both the dynamical model and its numerical resolution.
One simulation per pixel
For an image of width , height , and at most integration steps, the direct algorithm performs particle updates. The two implementations organize that workload differently.
Python renderer
two_suns.py uses NumPy arrays shaped like the image. Position, velocity, assignment state, and winner are stored for every pixel at once. Each integration step computes both gravitational accelerations with vectorized array operations. Boolean masks classify new captures, and the loop exits early if every particle has been assigned.
After the simulation, two masks map the winner array to the selected RGB colors. Pillow writes the resulting uint8 array as a PNG, while tqdm reports progress. Command-line options expose output size, sun coordinates, colors, , time step, capture radius, step limit, softening, and output filename, making the renderer suitable for scripted high-resolution experiments.
Browser renderer
The web app is a single static index.html with no backend. JavaScript stores positions and velocities in Float32Array buffers and winners in a Uint8Array. A nested loop advances only particles whose winner is still zero. Once classification is complete, the code writes RGBA values into ImageData and paints the result to an HTML canvas.
The browser interface lets the user:
- choose a width and height between 50 and 1200 pixels;
- select independent colors for the two basins;
- place the suns with two canvas clicks;
- render and preview the classification;
- reset the sun positions;
- export the canvas as
two-suns-basins.png.
Sun markers are drawn on top of the result so their positions remain visible. Because all computation happens locally in the browser, the same static files can be hosted directly by GitHub Pages. Large canvases require proportionally more memory and computation, so wallpaper-scale renders can take noticeably longer than small previews.
From dynamics to wallpapers
The visualizer is intentionally both scientific and playful. A productive workflow is to test the geometry at a modest resolution, adjust the two centers until the boundary has the desired balance, choose a restrained two-color palette, and then repeat the render at the target screen aspect ratio. The PNG exporter preserves the canvas’s actual pixel dimensions rather than its responsive on-screen size.
Symmetric sun positions produce symmetric fields, but symmetry in the final image also depends on the rectangular pixel lattice and tie-breaking rules. Asymmetric placements create sweeping regions and off-center boundaries that work particularly well as wallpaper compositions. The image is not a texture pasted over a simulation: each colored pixel is the recorded outcome of its own numerical trajectory.
Implementation map
index.htmlcontains the complete interactive application, typed-array solver, canvas renderer, controls, and PNG export.two_suns.pyis the configurable NumPy and Pillow command-line renderer.preview.ipynbis a notebook workspace for experimenting with the model.basins.pngandmedia/header.pngprovide rendered examples of the system.
References
- Magrini, M. Two Suns Gravity Visualizer: source code and browser application. GitHub, 2025.
- Newton, I. Philosophiae Naturalis Principia Mathematica, Book I, 1687. English translation available through the Internet Archive.
- Hairer, E., Lubich, C., and Wanner, G. Geometric Numerical Integration: Structure-Preserving Algorithms for Ordinary Differential Equations, 2nd ed., Springer, 2006.
- Grebogi, C., Ott, E., and Yorke, J. A. Fractal basin boundaries, long-lived chaotic transients, and unstable-unstable pair bifurcation. Physica D, 7(1-3), 181-200, 1983.
Two Suns Gravity Visualizer trasforma un semplice esperimento gravitazionale in arte generativa. Due soli sono fissi su un piano. Da ogni pixel di un’immagine viene rilasciata da ferma una particella di prova, ogni traiettoria viene integrata in avanti e il pixel assume il colore del sole che alla fine cattura la particella.
Il risultato è una mappa dei bacini di attrazione: un’immagine globale composta da centinaia di migliaia di problemi ai valori iniziali indipendenti. Le regioni uniformi indicano condizioni iniziali vicine con lo stesso esito, mentre i bordi intricati mostrano zone in cui un piccolo spostamento può cambiare il sole vincitore. Spostando i soli, modificando le proporzioni della tela e scegliendo una palette di colori, l’applicazione nel browser può generare immagini ad alta risoluzione adatte come sfondi.
Il modello fisico
Siano i due soli fissi nelle posizioni e , e sia la posizione di una particella di prova di massa unitaria. La simulazione usa sorgenti di uguale massa e coordinate dei pixel adimensionali. L’accelerazione è
Questa è la legge dell’inverso del quadrato in forma vettoriale: il numeratore punta verso un sole, mentre la divisione per il cubo della distanza lascia un’accelerazione di intensità proporzionale a . Il parametro combina la costante gravitazionale e la massa della sorgente in un’unica intensità regolabile.
Ogni coordinata dell’immagine diventa una condizione iniziale
I due corpi primari rimangono fissi e non si attraggono né orbitano l’uno intorno all’altro. Il modello è quindi un problema stilizzato a centri fissi, non una simulazione fisica completa del problema dei tre corpi. È progettato per mostrare una struttura geometrica, non per prevedere un sistema astronomico.
Come si forma l’immagine
Per ogni pixel iniziale, il risolutore pone una domanda binaria: la traiettoria entra prima nel disco di cattura del sole 1 o del sole 2? Tutte le posizioni iniziali che producono la stessa risposta formano il bacino di attrazione di quel sole.
Vicino a un sole, l’attrazione locale è in genere decisiva. Tra i soli e intorno al bordo dei bacini, invece, una particella può accelerare verso un centro, superarlo, attraversare il campo concorrente ed essere catturata in seguito dall’altro. Pixel vicini possono quindi descrivere percorsi molto diversi prima di ricevere colori differenti. L’immagine finale registra gli esiti senza disegnare le traiettorie.
La gravità di masse puntiformi pure è singolare nella posizione esatta di un sole. L’implementazione regolarizza le distanze al quadrato,
prima di calcolare . Il valore predefinito evita la divisione per zero e limita l’overflow numerico senza ingrandire visibilmente i soli.
Integrazione numerica
L’equazione del secondo ordine viene rappresentata come sistema del primo ordine
Ogni traiettoria viene fatta avanzare con il metodo di Eulero semi-implicito, detto anche Eulero simplettico:
L’aggiornamento della posizione con la nuova velocità è la differenza fondamentale rispetto al metodo di Eulero in avanti. È economico e in genere si comporta meglio per il moto hamiltoniano, quindi rappresenta un buon compromesso quando lo stesso aggiornamento deve essere applicato centinaia di volte a ogni pixel.
Il renderer Python predefinito usa , , un raggio di cattura di 3 pixel e un massimo di 800 passaggi. La versione per browser usa le stesse costanti fisiche e lo stesso raggio di cattura, con un limite di 700 passaggi. Se una particella entra in entrambi i dischi di cattura nello stesso passaggio, vince il sole più vicino. Se non entra in nessuno dei due dischi entro il limite, viene assegnata al sole più vicino nella posizione simulata finale. Questa regola garantisce un colore a ogni pixel, ma va interpretata come criterio di rendering e non come cattura fisica dimostrata.
I parametri rendono visibile anche la natura numerica dell’immagine. Passi temporali più grandi sono più veloci, ma possono oltrepassare un disco di cattura piccolo; passi più piccoli risolvono meglio gli incontri ravvicinati, ma aumentano il tempo di rendering. Il raggio di cattura e il numero massimo di passaggi modificano la classificazione delle traiettorie difficili. Il bordo generato dipende quindi sia dal modello dinamico sia dalla sua risoluzione numerica.
Una simulazione per ogni pixel
Per un’immagine di larghezza , altezza e al massimo passaggi di integrazione, l’algoritmo diretto esegue aggiornamenti delle particelle. Le due implementazioni organizzano il lavoro in modo diverso.
Renderer Python
two_suns.py usa array NumPy con la stessa forma dell’immagine. Posizione, velocità , stato di assegnazione e vincitore sono memorizzati contemporaneamente per ogni pixel. A ogni passaggio di integrazione vengono calcolate entrambe le accelerazioni gravitazionali mediante operazioni vettoriali sugli array. Maschere booleane classificano le nuove catture e il ciclo termina in anticipo quando tutte le particelle sono state assegnate.
Dopo la simulazione, due maschere associano l’array dei vincitori ai colori RGB scelti. Pillow salva l’array uint8 risultante come PNG, mentre tqdm mostra l’avanzamento. Le opzioni da riga di comando espongono dimensioni dell’output, coordinate dei soli, colori, , passo temporale, raggio di cattura, limite di passaggi, regolarizzazione e nome del file, rendendo il renderer adatto a esperimenti automatizzati ad alta risoluzione.
Renderer nel browser
L’applicazione web consiste in un singolo index.html statico senza backend. JavaScript memorizza posizioni e velocità in buffer Float32Array e i vincitori in un Uint8Array. Un ciclo annidato fa avanzare soltanto le particelle il cui vincitore è ancora zero. Terminata la classificazione, il codice scrive valori RGBA in ImageData e disegna il risultato su un canvas HTML.
L’interfaccia permette di:
- scegliere larghezza e altezza tra 50 e 1200 pixel;
- selezionare colori indipendenti per i due bacini;
- posizionare i soli con due clic sul canvas;
- eseguire il rendering e vedere l’anteprima della classificazione;
- ripristinare le posizioni dei soli;
- esportare il canvas come
two-suns-basins.png.
I marcatori dei soli vengono disegnati sopra il risultato, così le loro posizioni rimangono visibili. Poiché tutto il calcolo avviene localmente nel browser, gli stessi file statici possono essere pubblicati direttamente con GitHub Pages. Tele di grandi dimensioni richiedono proporzionalmente più memoria e calcolo, quindi i rendering in formato sfondo possono richiedere molto più tempo delle piccole anteprime.
Dalla dinamica agli sfondi
Il visualizzatore è volutamente scientifico e giocoso. Un flusso di lavoro efficace consiste nel provare la geometria a una risoluzione contenuta, regolare i due centri fino a ottenere un bordo ben bilanciato, scegliere una palette sobria di due colori e ripetere il rendering con le proporzioni dello schermo di destinazione. L’esportazione PNG conserva le dimensioni reali in pixel del canvas, non quelle responsive visualizzate sullo schermo.
Posizioni simmetriche dei soli producono campi simmetrici, ma la simmetria dell’immagine finale dipende anche dalla griglia rettangolare dei pixel e dalle regole per risolvere i pareggi. Disposizioni asimmetriche creano ampie regioni e bordi decentrati particolarmente adatti alla composizione di uno sfondo. L’immagine non è una texture sovrapposta a una simulazione: ogni pixel colorato rappresenta l’esito registrato della propria traiettoria numerica.
Mappa dell’implementazione
index.htmlcontiene l’applicazione interattiva completa, il risolutore basato su typed array, il renderer canvas, i controlli e l’esportazione PNG.two_suns.pyè il renderer configurabile da riga di comando basato su NumPy e Pillow.preview.ipynbè un notebook per sperimentare con il modello.basins.pngemedia/header.pngcontengono esempi generati dal sistema.
Riferimenti
- Magrini, M. Two Suns Gravity Visualizer: source code and browser application. GitHub, 2025.
- Newton, I. Philosophiae Naturalis Principia Mathematica, Book I, 1687. English translation available through the Internet Archive.
- Hairer, E., Lubich, C., and Wanner, G. Geometric Numerical Integration: Structure-Preserving Algorithms for Ordinary Differential Equations, 2nd ed., Springer, 2006.
- Grebogi, C., Ott, E., and Yorke, J. A. Fractal basin boundaries, long-lived chaotic transients, and unstable-unstable pair bifurcation. Physica D, 7(1-3), 181-200, 1983.