Skip to content

Instantly share code, notes, and snippets.

@camb416
Last active June 19, 2016 15:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save camb416/3af0f9bed558b04e89fdcf5f4f5e996c to your computer and use it in GitHub Desktop.
Save camb416/3af0f9bed558b04e89fdcf5f4f5e996c to your computer and use it in GitHub Desktop.
Interactive Draggable Bezier Path in Processing
Bezier b;
ArrayList<DraggablePoint> pts;
boolean isDragging;
int dragID;
float slope;
float t;
void setup(){
t = 0.0f;
isDragging = false;
dragID = -1;
size(1280,720);
b = new Bezier();
b.a = new DraggablePoint(random(width),random(height));
b.ca = new DraggablePoint(random(width),random(height));
b.cb = new DraggablePoint(random(width),random(height));
b.b = new DraggablePoint(random(width),random(height));
pts = new ArrayList<DraggablePoint>();
pts.add(b.a);
pts.add(b.b);
pts.add(b.ca);
pts.add(b.cb);
}
void draw(){
t += 0.0025f;
if(t>1.0f){
t = 0.0f ;
}
background(255);
b.draw();
Point p = b.plot(t);
stroke(0,32,64);
noFill();
ellipse(p.x,p.y,10,10);
Point slopePtA = new Point(p.x+cos(slope)*30, p.y+sin(slope)*30);
Point slopePtB = new Point(p.x+cos(slope)*-30, p.y+sin(slope)*-30);
line(p.x,p.y,slopePtA.x,slopePtA.y);
line(p.x,p.y,slopePtB.x,slopePtB.y);
// println(dragID);
}
void mouseDragged(){
if(isDragging){
DraggablePoint thisPt = pts.get(dragID);
thisPt.x = mouseX;
thisPt.y = mouseY;
}
}
void mouseMoved(){
int nearestID = -1;
float nearestDist = 100; // nearer than 100 selects
for(int i=0;i<pts.size();i++){
DraggablePoint thisPt = pts.get(i);
thisPt.isSelected = false;
float thisDist = dist(thisPt.x,thisPt.y,mouseX,mouseY);
if(thisDist<nearestDist){
nearestDist = thisDist;
nearestID = i;
}
}
if(nearestID>-1){
pts.get(nearestID).isSelected = true;
}
}
void mousePressed(){
for(int i=0;i<pts.size();i++){
DraggablePoint thisPt = pts.get(i);
if(thisPt.isSelected == true){
thisPt.isDragging = true;
dragID = i;
isDragging = true;
}
}
}
void mouseReleased(){
isDragging = false;
pts.get(dragID).isDragging = false;
dragID = -1;
}
class Point{
float x,y;
Point(float _x, float _y){
x = _x;
y = _y;
}
}
class DraggablePoint extends Point{
boolean isSelected;
boolean isDragging;
DraggablePoint(float _x, float _y){
super(_x,_y);
isSelected = isDragging = false;
}
void draw(){
if(isDragging){
noStroke();
fill(0,255,0);
} else if(isSelected){
noStroke();
fill(255,0,0);
} else {
noStroke();
fill(0);
}
ellipse(x,y,5,5);
}
}
class Bezier{
DraggablePoint a,b,ca,cb;
// plot a point along the curve
Point plot(float pct_in){
float pct = max(0.0f,min(pct_in,1.0f));
float cX = 3*(ca.x-a.x);
float bX = 3*(cb.x-ca.x)-cX;
float aX = b.x-a.x-cX-bX;
float cY = 3*(ca.y-a.y);
float bY = 3*(cb.y-ca.y)-cY;
float aY = b.y-a.y-cY-bY; // +ofRandom(-10,10);
// get the slope
// http://stackoverflow.com/a/15399173
float t = pct;
float B0_dt = -3*(1-t)*(1-t);
float B1_dt = 3*(1-t)*(1-t) -6*t*(1-t);
float B2_dt = - 3*t*t + 6*t*(1-t);
float B3_dt = 3*t*t;
float px_dt = (B0_dt * a.x) + (B1_dt * ca.x) + (B2_dt * cb.x) + (B3_dt * b.x);
float py_dt = (B0_dt * a.y) + (B1_dt * ca.y) + (B2_dt * cb.y) + (B3_dt * b.y);
slope = atan2(py_dt,px_dt);
//println(slope);
Point returnVal = new Point(0,0);
returnVal.x = aX*pct*pct*pct + bX*pct*pct + cX*pct + a.x; //+ofRandom(-5,5);
returnVal.y = aY*pct*pct*pct + bY*pct*pct + cY*pct + a.y;
text("a",aX,aY);
text("b",bX,bY);
text("c",cX,cY);
return returnVal;
}
void draw(){
stroke(0);
noFill();
bezier(a.x,
a.y,
ca.x,
ca.y,
cb.x,
cb.y,
b.x,
b.y);
stroke(128);
line(a.x,a.y,
ca.x,ca.y);
line(b.x,b.y,
cb.x,cb.y);
a.draw();
b.draw();
ca.draw();
cb.draw();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment