/*Simulates a bubble chamber, a device used to discover and
measure subatomic particles. Particles shot through the
chamber produce distinct patterns based on their mass, charge,
and the magnetic field in the chamber. Observing their patterns
allows scientists to infer data about these particles.
I find the patterns oddly attractive, and try to recreate them
here.
*/
/*This is by no means an accurate simulation, it attempts to
capture the visual asthetic. The mouseX approximates to something
relatively close to the strength of the magnetic field, while
mouseY is roughly the velocity of a charged particle. Particles
have a given mass, charge and location. By having the mouseX and
mouseY acting on a constant array of objects, we can see how their
values alter the scene.
*/
/*This program uses GPL'ed code (The vector class), and as such is bound by the
GNUPublic License version 2, or version 3.
*/
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 or version 3.
import processing.pdf.*;
//boolean saveOneFrame = false;
float spect = 25;
int num = 20;
float[] seed, mass, velo, jitt, sneu;
Particle[] electron, positron, sneutron;
float yness = 0;
float xness;
Vector vCur;
void setup(){
size(600,600);
background(0);
stroke(255);
//smooth();
electron = new Particle[num];
positron = new Particle[num];
sneutron = new Particle[num];
randomSeed(13);
seed = new float[num];
mass = new float[num];
velo = new float[num];
jitt = new float[num];
sneu = new float[num];
vCur = new Vector();
for(int i = 0; i < num; i++){
seed[i] = random(((width/2)-spect), ((width/2)+spect));
mass[i] = random(.98, 1.02);
velo[i] = random(-1, 1);
jitt[i] = random(-.01, .01);
sneu[i] = random(-.75, .75);
}
yness = (400-mouseY)/150.0;
xness = (mouseX+1)/((width*64.0));
for(int i = 0; i < num; i++){
vCur.a = -yness;
vCur.b = 0;
positron[i] = new Particle(seed[i], height, mass[i]+jitt[i], -1, vCur, xness);
sneutron[i] = new Particle(seed[i], height, mass[i]+jitt[i], sneu[i], vCur, xness);
vCur.a += jitt[i];
electron[i] = new Particle(seed[i], height, mass[i], 1, vCur, xness);
}
}
void draw(){
/*
if(saveOneFrame){
beginRecord(PDF, "particle2-" + mouseX + "-" + mouseY +".pdf");
}
*/
background(0);
stroke(255);
strokeWeight(.25);
translate(-25,125);
rotate(-PI/12);
yness = (height-mouseY)/150.0;
xness = (mouseX+1)/((width*64.0));
for(int i = 0; i < num; i++){
vCur.a = -yness + velo[i];
vCur.b = 10*jitt[i];
electron[i].reset(seed[i], height, mass[i], 1, vCur, xness);
positron[i].reset(seed[i], height, mass[i]+jitt[i], -1, vCur, xness);
sneutron[i].reset(seed[i], height, mass[i], sneu[i], vCur, xness);
}
for (int i = 0; i < 1000; i++){
for(int j = 0; j < num; j++){
electron[j].update();
positron[j].update();
sneutron[j].update();
}
}
/*
if (saveOneFrame){
endRecord();
saveOneFrame = false;
}
*/
}
/*
void mousePressed(){
saveOneFrame = true;
}
*/
class Particle{
float x, y, oldX, oldY;
float mass, charge;
Vector vect;
float decay;
Particle(float X, float Y, float Mass, float Charge, Vector Vect, float Decay){
reset(X, Y, Mass, Charge, Vect, Decay);
}
void update(){
line(oldX,oldY, x,y);
//point(x,y);
apply(1.02);
oldX = x;
oldY = y;
x+=charge*vect.magnitude()*sin(vect.dir());
y+=vect.magnitude()*cos(vect.dir());
}
void apply(float field){
Vector temp = vect.normal();
float toss = vect.magnitude();
decay = decay*field*mass*abs(charge);
temp.set(decay, temp.dir());
vect = vect.add(temp);
vect.set(toss, vect.dir());
}
void reset(float X, float Y, float Mass, float Charge, Vector Vect, float Decay){
x = X;
y = Y;
mass = Mass;
charge = Charge;
vect = Vect;
decay = Decay;
oldX = x;
oldY = y;
}
}
class ParticleGun{
float x, y;
float force, rotation;
}
/*This is an adaptation of the vector class written by
Ali Eslami
http://www.arkitus.com
*/
class Vector
{
float a;
float b;
//Null Vector
Vector(){
a = 0;
b = 0;
}
Vector(float A, float B){
a = A;
b = B;
}
float magnitude(){
return sqrt(pow(a,2)+pow(b,2));
}
float magcheap(){
return (a*a + b*b);
}
//Returns the angle of the vector relative
//to the positive x axis
float dir(){
return atan2(b,a);
}
Vector multiply(float k){
return new Vector(k*a, k*b);
}
Vector add(Vector V){
return new Vector(a+V.a, b+V.b);
}
//Dot Product
float dot(Vector V){
return (a*V.a + b*V.b);
}
//Y flipped Normal
Vector normal(){
return new Vector(-b,a);
}
//Set Vector by magnitude and direction
void set(float L, float D){
a = L*cos(D);
b = L*sin(D);
}
}