/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.lrs9Em$F0xB/rev.698
*
* authors:
* Wolfe
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
//This is meant for java processing
//Overloading functions and java libary work with array doesn't work
//Copy to Processing editor
//uncomment line // bez_DrawSPLine(100, color(255, 0, 0), points, 3);
//You will be able to add new points and to see quadratic Bezier curve (not cubic only)
// Maybe once I'll remake it for javascript processing too
// Green - Catmull-Rom; Blue - cubic Bezier
// You can still move the points in javascript processing version but cannot add another
// cp_DrawSPLine (int segments, color color, PVector[] points, boolean loop)
// bez_DrawSPLine (int segments, color color, PVector[] points, int params) { //params: 3=quadratic, 4=cubc
int highlighted = -1;
int locked = -1;
float highlightArea = 30;
// numbers labels
float numAngle= TWO_PI - QUARTER_PI;
float numSpacing = 15;
float numSpacingHL = 30;
float numSpacingLk = 25;
PVector[] points = new PVector[7];
void setup() {
size(600, 400);
background(0);
noSmooth();
for (int i=0; i<points.length; i++) {
points[i] = new PVector(random(20, width-20), random(20, height-20));
}
}
void draw() {
background(0);
DrawPoints(color(255, 100), color(200, 90), 10, points);
DrawNumbers(color(255, 140), numSpacing, points);
DrawLines(color(255, 50), points);
cr_DrawSPLine(100, color(0, 200, 0), points, false);
bez_DrawSPLine(100, color(0, 0, 255), points, 4);
// bez_DrawSPLine(100, color(255, 0, 0), points, 3);
highlighted = Check();
if ((highlighted>=0) && (locked<0)) Highlight(highlighted, false);
if (locked>=0) {
points[locked] = new PVector(mouseX, mouseY);
Highlight(locked, true);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
void DrawNumbers(color clr, float spacing, PVector[] points) {
pushStyle();
fill(clr);
for (int i=0; i<(points.length); i++) {
if ((i == highlighted) && (locked<0)) {
// print(locked +" ");
spacing = numSpacingHL;
}
if (i == locked) {
spacing = numSpacingLk;
}
if ((i!=highlighted) && (i!=locked)) {
spacing = numSpacing;
}
PVector pos = new PVector(cos(numAngle)*spacing, sin(numAngle)*spacing);
textAlign(CENTER, CENTER);
text(i, points[i].x+pos.x, points[i].y+pos.y);
}
numAngle += 0.03;
popStyle();
}
/////////////////////////////////////
void DrawPoints(color strColor, color fillColor, float rad, PVector[] points) {
pushStyle();
stroke(strColor);
fill(fillColor);
for (int i=0; i<(points.length); i++) {
ellipse(points[i].x, points[i].y, rad, rad);
}
popStyle();
}
/////////////////////////////////////
void DrawLines(color clr, PVector[] points) {
pushStyle();
stroke(clr);
for (int i=0; i<(points.length); i++) {
if (i<points.length-1) {
line(points[i].x, points[i].y, points[i+1].x, points[i+1].y);
}
}
popStyle();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////// CATMULL-ROM CURVE /////////////////////////////////////////////////////////////////////////
PVector CatmullRom (float t, PVector P0, PVector P1, PVector P2, PVector P3) { // cubic
float t2 = t*t; // squared
float t3 = t2*t; // cubed
float x = 0.5 * ((2*P1.x) + (-P0.x + P2.x)*t + (2*P0.x - 5*P1.x + 4*P2.x -P3.x) * t2 + (-P0.x + 3*P1.x - 3*P2.x + P3.x) * t3);
float y = 0.5 * ((2*P1.y) + (-P0.y + P2.y)*t + (2*P0.y - 5*P1.y + 4*P2.y -P3.y) * t2 + (-P0.y + 3*P1.y - 3*P2.y + P3.y) * t3);
return new PVector (x, y);
}
/////////////////////////////////////
void DrawCatmullRom (int segments, color clr, PVector P0, PVector P1, PVector P2, PVector P3) {
PVector currPos, prevPos;
pushStyle();
for (float i=0; i<segments; i++) {
currPos = CatmullRom(i/segments, P0, P1, P2, P3);
prevPos = CatmullRom((i-1)/segments, P0, P1, P2, P3);
stroke(clr);
line(prevPos.x, prevPos.y, currPos.x, currPos.y);
}
popStyle();
}
/////////////////////////////////////
void cr_DrawSPLine (int segments, color clr, PVector[] splineCR, boolean looped) {
for (int i=0; i<(splineCR.length-3); i++) {
DrawCatmullRom(segments, clr, splineCR[i], splineCR[i+1], splineCR[i+2], splineCR[i+3]);
}
if (looped) {
DrawCatmullRom(segments, clr, splineCR[splineCR.length-1], splineCR[0], splineCR[1], splineCR[2]);
DrawCatmullRom(segments, clr, splineCR[splineCR.length-3], splineCR[splineCR.length-2], splineCR[splineCR.length-1], splineCR[0]);
DrawCatmullRom(segments, clr, splineCR[splineCR.length-2], splineCR[splineCR.length-1], splineCR[0], splineCR[1]);
}
}
///////////////// CATMULL-ROM CURVE /////////////////////////////////////////////////////////////////////////
/////////////////// BEZIER CURVE ///////////////////////////////////////////////////////////////////////////
///// QUADRATIC /////
PVector Bezier(float t, PVector P0, PVector P1, PVector P2) {
float t2 = t*t; // squared
float b1 = 2*t*(1-t);
float b2 = (1-t)*(1-t);
float x = b2*P0.x + b1*P1.x + t2*P2.x;
float y = b2*P0.y + b1*P1.y + t2*P2.y;
return new PVector(x, y);
}
///// QUADRATIC /////
///// CUBIC /////
PVector Bezier(float t, PVector P0, PVector P1, PVector P2, PVector P3) {
float t2 = t*t; // squared
float t3 = t2*t; // cubed
float b1 = 3*t*t*(1-t);
float b2 = 3*t*(1-t)*(1-t);
float b3 = (1-t)*(1-t)*(1-t);
float x = b3 * P0.x + b2 * P1.x + b1 * P2.x + t3 * P3.x;
float y = b3 * P0.y + b2 * P1.y + b1 * P2.y + t3 * P3.y;
return new PVector(x, y);
}
///// CUBIC /////
//////// QUADRATIC /////////////////////////////
void DrawBezier (int segments, color clr, PVector P0, PVector P1, PVector P2) {
PVector currPos, prevPos;
pushStyle();
for (float i=0; i<segments; i++) {
currPos = Bezier(i/segments, P0, P1, P2);
prevPos = Bezier((i-1)/segments, P0, P1, P2);
stroke(clr);
line(prevPos.x, prevPos.y, currPos.x, currPos.y);
}
popStyle();
}
//////// QUADRATIC /////////////////////////////
//////// CUBIC /////////////////////////////
void DrawBezier (int segments, color clr, PVector P0, PVector P1, PVector P2, PVector P3) {
PVector currPos, prevPos;
pushStyle();
for (float i=0; i<segments; i++) {
currPos = Bezier(i/segments, P0, P1, P2, P3);
prevPos = Bezier((i-1)/segments, P0, P1, P2, P3);
stroke(clr);
line(prevPos.x, prevPos.y, currPos.x, currPos.y);
}
popStyle();
}
//////// CUBIC /////////////////////////////
void bez_DrawSPLine (int segments, color clr, PVector[] splineBez, int params) { // 3=quadratic, 4=cubc
if (params == 3) {
for (int i=0; i<splineBez.length; i+=2) { // quadratic
if (i+2>=splineBez.length) break;
//DrawBezier(segments, clr, splineBez[i], splineBez[i+1], splineBez[i+2]);
}
}
if (params == 4) {
for (int i=0; i<splineBez.length; i+=3) { // cubic
if (i+3>=splineBez.length) break;
DrawBezier(segments, clr, splineBez[i], splineBez[i+1], splineBez[i+2], splineBez[i+3]);
}
}
}
/////////////////// BEZIER CURVE ///////////////////////////////////////////////////////////////////////////
///////////////// CHECKS /////////////
int Check() {
float actDist;
float nearest = highlightArea + 1;
int nearestIndex = -1;
if (locked<0) {
for (int i=0; i<points.length; i++) {
PVector mouse = new PVector(mouseX, mouseY);
actDist= PVector.dist(mouse, points[i]);
if ((actDist<highlightArea) && (actDist<nearest)) {
nearestIndex = i;
nearest = actDist;
}
}
}
return nearestIndex;
}
///////////////// CHECKS /////////////
///////////////// HIGHLIGHT /////////////
void Highlight(int index, boolean lock) {
pushStyle();
colorMode(HSB, 360, 100, 100);
color stroHL = color (203, 91, 99, 250);
color fillHL = color (203, 91, 99, 90);
float radHL = 35;
color stroLk = color (359, 91, 99, 250);
color fillLk = color (359, 91, 99, 90);
float radLk = 25;
color strokeColor;
color fillColor;
float radius;
if (lock) {
strokeColor = (stroLk);
fillColor = (fillLk);
radius = radLk;
}
else {
strokeColor = (stroHL);
fillColor = (fillHL);
radius = radHL;
}
stroke(strokeColor);
fill(fillColor);
ellipse(points[index].x, points[index].y, radius, radius);
popStyle();
}
///////////////// HIGHLIGHT /////////////
//////////////// INPUT ////////////////////////////////////////////
void mousePressed() {
// only processing - java
if ((highlighted<0) && (locked<0)) {
PVector[] extended = new PVector[points.length+1];
extended[extended.length-1] = new PVector(mouseX, mouseY);
System.arraycopy(points, 0, extended, 0, points.length);
points = extended;
extended = null;
}
if ((highlighted>=0) && (locked<0)) {
locked = highlighted;
}
}
void mouseReleased() {
if (locked>=0) {
locked = -1;
}
}
//////////////// INPUT ////////////////////////////////////////////