> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.dOwn$MPNfCd/rev.217
 * 
 * authors: 
 *   Nuno Lopes

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



// Pressing Control-R will render this sketch.

// ORBITS OF AN 2D ODE SYSTEM
// Using Simple Euler scheme
// X'=A*X+B*Y+nlf(X,Y)
// Y'=C*X+D*Y 
// X=x-mouseX, Y=y-mouseY

// With a little bit of "copy/paste" of the amazing 
// Ari Prasetyo 'Follow' sketch


// change these values to have different linear part 
float A=-0.5;
float B=-.5;
float C=1.0;
float D=0.0;

//number of particles per orbit
int pnumber=300;

// time increment
float Dt=0;

float nlf(float x, float y){
  // change this to have different nonlinear interactions
  return  1./1000.*(y-mouseX)*(x-mouseX);
}

class Position {
  Position(float x, float y) {
    this.x = x;
    this.y = y;
  }

  private float x;
  private float y;

  public float X() {
    return x;
  }

  public float Y() {
    return y;
  }
}


class Particle {
  protected  float diam;  
  protected  Position location;

  Particle(Position location, float diam) {
    this.diam=diam;    
    this.location=location;
  }

  void UpdatePosition() {
    float newx=this.location.X();
    float newy=this.location.Y();

    newx=Dt*(A*(newx-mouseX)+B*(newy-mouseY))+
      nlf(newx,newy)+newx;
    newy=Dt*(C*(newx-mouseX)+D*(newy-mouseY))+newy;
    this.location = new Position(newx, newy);
  }

  void draw(int clr) {
    fill(255-clr, 0, clr, 150);
    ellipse(this.location.X(), this.location.Y(), this.diam, this.diam);
  }
}


Particle p;

void setup() {
  frameRate(30);
  background(255);
  size(400, 400);
  smooth();
  Dt=0.1;
}  

void draw() {
  clear();
  p = new Particle(new Position(random(400), random(400)), random(5));
  for (int i=0;i<pnumber;i++) {
    int clr=255-i*255/pnumber;
    p.UpdatePosition();
    p.draw(clr);
  }
}

void mousePressed(){
loop();
}

void mouseReleased(){
    noLoop();
}
 
void clear() {
  fill(255, 3);
  noStroke();
  rect(0, 0, width, height);
}