/*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);
  }
}
Project 2: