> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://cd3d.sketchpad.cc/sp/pad/view/ro.YYq22Ud-aH-/rev.23
 * 
 * authors: 
 *   Pascal Romon

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



/*
This simple program draws a curve by the flow of 
 the circular field
 Pascal Romon 2016-09-30 
 with contribution of Celine Noel for building the curve with the mouse
 */

/*
Start drawing a curve by pressing 'c'; 
 if a curve already eists, it is erased and a new one is created
 Finish by 'c' for a closing the curve
 Flow by 'f' (only if the curve exists)
 */


int vertexSize = 10;  // circle size for drawing vertices
Curve C;
int n;
float tau = 0.1;
boolean pause = false;  // control the mouse during the flow
boolean make_curve = false; // set to true to create the curve
boolean startFlow = false;  // set to true to start the flow

void setup() {
  frameRate(10);
  size(300, 300);
  background(100);
  C = new Curve();
}

void draw() {
  translate(width/2, height/2);  // sets the origin of the coordinates in the center of the frame

  if (C.vertices.size() > 0) {
    C.drawCurve();
  }

  if (startFlow && !pause) {
    background(100);
    C.drawCurve();

    ArrayList<Vector> flow = new ArrayList<Vector>();
    flow = badRotationFlow(C);
    C.shift(flow);
  }
}

ArrayList<Vector> badRotationFlow(Curve Ctemp) {
  ArrayList<Vector> ts = new ArrayList<Vector>();
  for (int i = 0; i < Ctemp.vertices.size(); i++) {
    Vector v = new Vector();
    v.x = Ctemp.vertices.get(i).x;
    v.y = Ctemp.vertices.get(i).y;
    v.rot();
    v.mult(tau);
    ts.add(v);
  }
  for (int j = 0; j < ts.size(); j++) {
    Vector v = ts.get(j);
  }
  return(ts);
}

void mouseClicked() {
  if (make_curve) {
    C.addVertex(mouseX - width / 2, mouseY - height / 2);
  }
  if (startFlow) {
    pause = !pause; // during the flow, clicking pause and restarts the process
  }
}

void keyReleased() {
  if (key == 'c') {
    startFlow = false; //interrupts flow
    if (make_curve && C.vertices.size() >= 3) {  // we close the loop
      C.loop = true;
    } else {  // we start a new loop
      background(100);
      C.vertices.clear();
      C.loop = false;
    }
    make_curve = !make_curve;
  }
  if (key == 'f' && make_curve == false) {
    startFlow = true;
  }
}

class Vector {
  float x = 0.0;
  float y = 0.0;
  
  Vector() {
  }
  
  Vector(float xi,float yi) {
    x = xi;
    y = yi;
  }

  void add(Vector v) {
    x += v.x;
    y += v.y;
  }
  void sub(Vector v) {
    x-= v.x;
    y-= v.y;
  }
  
  void mult(float c) {
    x = x*c;
    y = y*c;
  }

  float det(Vector v) {
    return (x * v.y - y *v.x);
  }

  float scal(Vector v) {
    return (x * v.x + y *v.y);
  }

  float norm() {
    return(sqrt((x*x+y*y)));
  }
  float normsq() {
    return((x*x+y*y));
  }
  void normalize() {
    float mag = sqrt ((float)(x*x+y*y));
    x = x/mag;
    y= y/mag;
  }
  void rot() {
    float u, v;
    u=x;
    v=y;
    x= -v;
    y = u;
  }
}

class Curve {
  ArrayList<Vector> vertices = new ArrayList<Vector>();
  boolean loop;  // if true, indicate only n vertices

  void drawCurve() {
    int n = vertices.size();
    Vector current,next;
    //first: lines
    for(int i=0; i < n-1; i++) {
      current = vertices.get(i);
      next = vertices.get(i+1);
      line((float)current.x,(float)current.y,(float)next.x,(float)next.y);
    }
    current = vertices.get(n-1);  // last point
    if (loop) {
      next = vertices.get(0);
      line((float)current.x,(float)current.y,(float)next.x,(float)next.y);
    }
    // second: vertices
    for(int i=0; i < n-1; i++) {
      current = vertices.get(i);
      next = vertices.get(i+1);
      //println(i,current.x, current.y);
      ellipse((float)current.x,(float)current.y,vertexSize,vertexSize);
    }
    current = vertices.get(n-1);  // last point
    ellipse((float)current.x,(float)current.y,vertexSize,vertexSize);
  }
  
  void addVertex(float xnew, float ynew) { // adds a vertex
    Vector v = new Vector(xnew,ynew);
    vertices.add(v);
  }
  
  void shift(ArrayList<Vector> shifts) {
    // one should check that the size of both list is the same ...
    //Vector v,s;
    for (int i = 0; i < vertices.size(); i++) {
      Vector v = vertices.get(i);
      Vector s = shifts.get(i);
      //vertices.get(i).add(s);
      v.x += s.x;
      v.y += s.y;
    }
  }
}