> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://p5js.sketchpad.cc/sp/pad/view/ro.SP7RhUmtC$$/rev.1096
 * 
 * authors: 
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   Kris Frajer
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   
 *   f
 *   

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




'use strict'; 
var astr;

// this is run once.   
function setup() {  

  createCanvas(400, 600);
  stroke(5);

  astr = new VibrantString(20, width/3.0, 25.0);
  astr.setOffset(0, -height/4);
  astr.setAngle(90);
} 


// this is run repeatedly.  
function draw() { 
  translate(width/2.0, height/2.0); 
  astr.setOffset(0, mouseY-height/2);
  noStroke();
  fill('#00ffff');
  rect(-width/2.0,-height/2.0,width/2.0,height);
  fill('#F09494');
  rect(0,-height/2.0,width/2.0,height);


  //astr.drawPoints();
  astr.drawVerteces();
  astr.updatePoints();

}

function mouseReleased() {
  astr.plokString();
}

function VibrantString(_n, _len, _amp) {

  this.harmonic = 1;

  this.n = _n;    //Number of points
  this.pts = [];

  this.amp = _amp;
  this.len = _len;
  this.f = 0.5;
  this.time = millis();  
  this.k=0;   
  this.deltak=0.04;  //Damping constant

  this.r=3;  //Radius of points

  this.theta=0;
  this.xOffset=0;
  this.yOffset=0;
  
  this.c1=color('#00ffff');
  this.c2=color('#F09494');
  this.cc=this.c1;

  for (let i=0; i<this.n; i++) {
    this.pts[i]=createVector(0, 0);
  }
  
  this.setOffset = function(xoff, yoff) {
    this.xOffset=xoff;
    this.yOffset=yoff;
  }

  this.drawPoints=function() {
    for (let i=0; i<this.n; i++) {
      var v=this.pts[i];
      ellipse(v.x, v.y, this.r, this.r);
    }
  }
  
  this.setAngle = function(a) {
    this.theta=a;   //Value in degrees, positive clockwise
  };

  this.drawPoints = function() {
    for (let i=0; i<this.n; i++) {
      var v=this.pts[i];
      ellipse(v.x, v.y, this.r, this.r);
    }
  };
  
  this.drawVerteces=function() {      
    
    fill(this.cc);
    beginShape();
    for (let i=0; i<this.n; i++) {
      var v=this.pts[i];    
      vertex(v.x, v.y);
    }

    var v=this.pts[0]; 
    vertex(v.x, v.y);      //Back to first point

    endShape(CLOSE);
  };

  
  //Points are assumed to be draw from 0 to length in steps dictated by len/n
  //Amplitude is measured wrt a zero baseline.
  this.updatePoints = function() {
    var px = -this.len/2.0;
    var stepx=this.len/((this.n-1)*1.0);
    this.time=millis();

    for (let i=0; i<this.n; i++) {

      var tx;
      var ty;

      tx=px;

      //y(x,t)=Amp * sin(n*PI/L*x)cos(2*PI*freq*time)
      var equationBody=this.amp*sin(this.harmonic*PI/this.len*(px+this.len/2.0))*cos(2*PI*this.f*this.time/1000.0);
      ty=equationBody;                //UPDATES position
      if(equationBody>0) 
        this.cc=this.c2;
      else
        this.cc=this.c1;
      ty-=this.k*equationBody;        //DAMPING factor
      

      //Rotation matrix about center follow by translation
      var a=radians(this.theta);
      this.pts[i].x= (tx*cos(a) - ty*sin(a) ) + this.xOffset;
      this.pts[i].y= (ty*cos(a) + tx*sin(a) ) + this.yOffset;

      px+=stepx;
    }

    if (this.k<1)
      this.k+=this.deltak;   //Damping factor rate
    else 
      this.k=1.0;
  };

  this.plokString = function() {
    this.f=random(0.5, 3);
    this.k=0;
    this.time=millis();
  }; 


}