import processing.core.*; 
import processing.xml.*; 

import java.applet.*; 
import java.awt.Dimension; 
import java.awt.Frame; 
import java.awt.event.MouseEvent; 
import java.awt.event.KeyEvent; 
import java.awt.event.FocusEvent; 
import java.awt.Image; 
import java.io.*; 
import java.net.*; 
import java.text.*; 
import java.util.*; 
import java.util.zip.*; 
import java.util.regex.*; 

public class Spiromatic extends PApplet {

float angle = 0.0f;
float ANGLE_CHANGE = 0.05f;
final float MIN_DISTANCE = 5f;

ArrayList<Line> myLines = new ArrayList<Line>();

public void setup()
{
    addMouseWheelListener(new java.awt.event.MouseWheelListener() { 
    public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { 
      mouseWheel(evt.getWheelRotation());
  }});
  
  size(800,600,P3D);
  smooth();
  noFill();
  stroke(255); 
  myLines.add(new Line()); 
}

public void mouseWheel(int delta) {
  if ( delta < 0 )
    ANGLE_CHANGE -= 0.01f;
  else
    ANGLE_CHANGE += 0.01f;
}

public void draw()
{
  background(0);
  translate(width/2,height/2);
  rotateZ(angle);
  angle += ANGLE_CHANGE;
  if ( angle >= TWO_PI )
    angle = 0.0f;
    
  for ( int i=0; i < myLines.size(); i++ )
  {
    Line l = myLines.get(i);
    //l.RotatePoints(angle);
    l.Draw();
  }
  
  if ( mousePressed )
  {
    translate(-width/2, -height/2); 
    PVector vect = new PVector(mouseX - (width/2), mouseY - (height/2) );
    float m = vect.mag();
    PVector rotation = new PVector( m*cos(angle), m*sin(angle) );
    
    myLines.get(myLines.size()-1).AddPoint(rotation);
  }
 
  
}

public void mouseReleased()
{
  myLines.add(new Line());
}

public void keyPressed()
{
  if ( keyCode == ENTER )
  {
    myLines.clear();
    myLines.add(new Line());
  }
}

public void Rotate(boolean on)
{
  int m;
  if ( on ) 
    m = 1;
  else
    m = -1;
    
  
  rotateZ(m*angle);
  angle += ANGLE_CHANGE;
  if ( angle >= TWO_PI )
    angle = 0.0f;
  
}


class Line
{
  private ArrayList<PVector> myPoints = new ArrayList<PVector>();
  private float r,g,b;
  
  public Line()
  {
    r = random(32,255);
    g = random(32,255);
    b = random(32,255);
  }
  
  public void RotatePoints(float angle)
  {
    PVector rotation = new PVector(cos(angle), sin(angle));
    for ( int i=0; i < myPoints.size(); i++ )
    {
      PVector p = myPoints.get(i);
      p.add(rotation);
    }
  }
  public void Draw()
  {
    
    
    if ( myPoints.size() < 1 )
     return;
     
    PVector first = myPoints.get(0);
    
    PVector last = myPoints.get(myPoints.size()-1);
    
    beginShape();
    curveVertex(first.x, first.y);
    
    for ( int i=0; i < myPoints.size(); i++ )
    {
      if ( i < 256 )
        stroke ( min(i+32,r), min(i+32,g), min(i+32,b) );
      else
        stroke (r,g,b);
        
      PVector p = myPoints.get(i);
      curveVertex(p.x, p.y);
    }
    
    curveVertex(last.x, last.y);
    endShape();
  }
  public void AddPoint(PVector p)
  {
    if ( myPoints.size() < 1 || p.dist(myPoints.get(myPoints.size()-1)) > MIN_DISTANCE )
      myPoints.add(p);
  }
}


  static public void main(String args[]) {
    PApplet.main(new String[] { "--bgcolor=#F0F0F0", "Spiromatic" });
  }
}
