Last active
June 19, 2016 15:57
-
-
Save camb416/3af0f9bed558b04e89fdcf5f4f5e996c to your computer and use it in GitHub Desktop.
Interactive Draggable Bezier Path in Processing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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