ArrayList <PVector> path;
color red, yellow, blue, black;
red = color(186, 45, 50);
yellow = color(247, 220, 89);
blue = color(7, 39, 136);
buffer = createGraphics(width, height, P2D);
path = new ArrayList<PVector>();
path.add(new PVector(mouseX, mouseY));
line(pmouseX, pmouseY, mouseX, mouseY);
if (dist(path.get(path.size()-1).x, path.get(path.size()-1).y, mouseX, mouseY)>1) {
path.add(new PVector(mouseX, mouseY));
FatCurve fc = new FatCurve(path, weight);
fc.drawCurve(red, 3, yellow, buffer);
BezierSpline bs = new BezierSpline(path, false);
bs.drawStroke(blue, 3, buffer);
buffer.background(black);
PFont pf = createFont("Helvetica", 20);
buffer.textAlign(CENTER, CENTER);
buffer.text("Draw! Press c to clear.", width/2, 20);
BezierSpline(ArrayList<PVector> path, boolean closed) {
if (emptyPath) { return; }
vertex(anch[0].x, anch[0].y);
for (int i = 1; i<anch.length; i++) {
bezierVertex(ctr[j].x, ctr[j].y, ctr[j+1].x, ctr[j+1].y, anch[i].x, anch[i].y);
void drawStroke(color sColor, int sWeight, PGraphics pg) {
if (emptyPath) { return; }
pg.strokeWeight(sWeight);
pg.vertex(anch[0].x, anch[0].y);
for (int i = 1; i<anch.length; i++) {
pg.bezierVertex(ctr[j].x, ctr[j].y, ctr[j+1].x, ctr[j+1].y,
void drawStrokeAndFill(color sColor, int sWeight, color fColor, PGraphics pg) {
if (emptyPath) { return; }
pg.strokeWeight(sWeight);
pg.vertex(anch[0].x, anch[0].y);
for (int i = 1; i<anch.length; i++) {
pg.bezierVertex(ctr[j].x, ctr[j].y, ctr[j+1].x, ctr[j+1].y,
void makeControlPoints(ArrayList<PVector> p) {
if (emptyPath) { return; }
ctr = new PVector[p.size()*2];
ctr = new PVector[(p.size()-1)*2];
for (int i=0; i<(p.size()-1); i++) {
float dx = p.get(i+1).x-p.get(i).x;
float dy = p.get(i+1).y-p.get(i).y;
ctr[j] = new PVector(p.get(i).x+dx/3, p.get(i).y+dy/3);
ctr[j+1] = new PVector(p.get(i).x+2*dx/3, p.get(i).y+2*dy/3);
PVector last = p.get(p.size()-1);
float dx = p.get(0).x-last.x;
float dy = p.get(0).y-last.y;
ctr[j] = new PVector(last.x+dx/3, last.y+dy/3);
ctr[j+1] = new PVector(last.x+2*dx/3, last.y+2*dy/3);
void makeAnchorPoints(ArrayList<PVector> p) {
if (emptyPath) { return; }
anch = new PVector[p.size()+1];
anch[0] = new PVector((ctr[0].x+ctr[ctr.length-1].x)/2,
(ctr[0].y+ctr[ctr.length-1].y)/2);
anch[anch.length-1] = new PVector(anch[0].x, anch[0].y);
anch = new PVector[p.size()];
anch[0] = new PVector(p.get(0).x, p.get(0).y);
anch[anch.length-1] = new PVector(p.get(p.size()-1).x, p.get(p.size()-1).y);
for (int i = 1; i<(anch.length-1); i++) {
anch[i] = new PVector((ctr[j].x+ctr[j+1].x)/2, (ctr[j].y+ctr[j+1].y)/2);
ArrayList<PVector> curve;
FatCurve(ArrayList<PVector> path, float curveWidth) {
curve = new ArrayList<PVector>();
curve.add(new PVector(path.get(0).x + radius, path.get(0).y));
curve.add(new PVector(path.get(0).x, path.get(0).y + radius));
curve.add(new PVector(path.get(0).x - radius, path.get(0).y));
curve.add(new PVector(path.get(0).x, path.get(0).y - radius));
makeSemiCircle(path, path.get(0), path.get(1));
makeSemiCircle(path, path.get(path.size()-1), path.get(path.size()-2));
BezierSpline b = new BezierSpline(curve, true);
void drawCurve(color strokeC, int sWeight, color fillC, PGraphics pg) {
BezierSpline b = new BezierSpline(curve, true);
b.drawStrokeAndFill(strokeC, sWeight, fillC, pg);
ArrayList<PVector> getCurve() {
void makeSemiCircle(ArrayList<PVector> p, PVector first, PVector second) {
float d = first.dist(second);
float dx = (second.x-first.x)/d;
float dy = (second.y-first.y)/d;
curve.add(new PVector(first.x +dy*radius, first.y-dx*radius));
curve.add(new PVector(first.x +(-0.87*dx+0.5*dy)*radius, first.y+(-0.5*dx-0.87*dy)*radius));
curve.add(new PVector(first.x +(-0.87*dx-0.5*dy)*radius, first.y+(0.5*dx-0.87*dy)*radius));
curve.add(new PVector(first.x -dy*radius, first.y+dx*radius));
void makeFirstHalf(ArrayList<PVector> p) {
for (int i = 0; i<(p.size()-1); i++) {
float dx = (p1.x-p0.x)/d;
float dy = (p1.y-p0.y)/d;
PVector mid = new PVector((p0.x+p1.x)/2, (p0.y+p1.y)/2);
curve.add(new PVector(mid.x-dy*radius, mid.y+dx*radius));
void makeSecondHalf(ArrayList<PVector> p) {
for (int i = (p.size()-1); i>0; i--) {
float dx = (p1.x-p0.x)/d;
float dy = (p1.y-p0.y)/d;
PVector mid = new PVector((p0.x+p1.x)/2, (p0.y+p1.y)/2);
curve.add(new PVector(mid.x-dy*radius, mid.y+dx*radius));