midilab_opendsp-mods/factory/video/dsp-processing/projects/Curves/ArcLengthParametrization/ArcLengthParametrization.pde
/*
  Arc Length parametrization of curves by Jakub Valtar

  This example shows how to divide a curve into segments
  of an equal length and how to move along the curve with
  constant speed.

  To demonstrate the technique, a cubic BÃ©zier curve is used.
  However, this technique is applicable to any kind of
  parametric curve.
*/

BezierCurve curve;

PVector[] points;
PVector[] equidistantPoints;

float t = 0.0;
float tStep = 0.004;

final int POINT_COUNT = 80;

int borderSize = 40;

void setup() {
  size(640, 360, P2D);
  
  frameRate(60);
  smooth(8);
  textAlign(CENTER);
  textSize(16);
  strokeWeight(2);
  
  PVector a = new PVector(   0, 300);
  PVector b = new PVector( 440,   0);
  PVector c = new PVector(-200,   0);
  PVector d = new PVector( 240, 300);

  curve = new BezierCurve(a, b, c, d);
  
  points = curve.points(POINT_COUNT);
  equidistantPoints = curve.equidistantPoints(POINT_COUNT);
}


void draw() {
  
  // Show static value when mouse is pressed, animate otherwise
  if (mousePressed) {
    int a = constrain(mouseX, borderSize, width - borderSize);
    t = map(a, borderSize, width - borderSize, 0.0, 1.0);
  } else {
    t += tStep;
    if (t > 1.0) t = 0.0;
  }
  
  background(255);
  
  
  // draw curve and circle using standard parametrization
  pushMatrix();
    translate(borderSize, -50);
    
    labelStyle();
    text("STANDARD\nPARAMETRIZATION", 120, 310);
    
    curveStyle();
    beginShape(LINES);
      for (int i = 0; i < points.length - 1; i += 2) {
        vertex(points[i].x, points[i].y);
        vertex(points[i+1].x, points[i+1].y);
      }
    endShape();
    
    circleStyle();
    PVector pos1 = curve.pointAtParameter(t);
    ellipse(pos1.x, pos1.y, 12, 12);
    
  popMatrix();
  
  
  // draw curve and circle using arc length parametrization
  pushMatrix();
    translate(width/2 + borderSize, -50);
    
    labelStyle();
    text("ARC LENGTH\nPARAMETRIZATION", 120, 310);
    
    curveStyle();
    beginShape(LINES);
      for (int i = 0; i < equidistantPoints.length - 1; i += 2) {
        vertex(equidistantPoints[i].x, equidistantPoints[i].y);
        vertex(equidistantPoints[i+1].x, equidistantPoints[i+1].y);
      }
    endShape();
    
    circleStyle();
    PVector pos2 = curve.pointAtFraction(t);
    ellipse(pos2.x, pos2.y, 12, 12);
    
  popMatrix();
  
  
  // draw seek bar
  pushMatrix();
    translate(borderSize, height - 45);
    
    int barLength = width - 2 * borderSize;
  
    barBgStyle();
    line(0, 0, barLength, 0);
    line(barLength, -5, barLength, 5);
    
    barStyle();
    line(0, -5, 0, 5);
    line(0, 0, t * barLength, 0);
    
    barLabelStyle();
    text(nf(t, 0, 2), barLength/2, 25);
  popMatrix();
  
}


// Styles -----

void curveStyle() {
  stroke(170);
  noFill();
}

void labelStyle() {
  noStroke();
  fill(120);
}

void circleStyle() {
  noStroke();
  fill(0);
}

void barBgStyle() {
  stroke(220);
  noFill();
}

void barStyle() {
  stroke(50);
  noFill();
}

void barLabelStyle() {
  noStroke();
  fill(120);
}



