class Bezier { Bezier() { anchors = new PParticle[2]; controls = new PParticle[2]; anchors[0] = new PParticle(0, 0, physics); anchors[1] = new PParticle(0, 0, physics); controls[0] = new PParticle(0, 0, physics); controls[1] = new PParticle(0, 0, physics); setupPoints(); selectedPoint = null; } Bezier(float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2) { anchors = new PParticle[2]; controls = new PParticle[2]; anchors[0] = new PParticle(x1, y1, physics); anchors[1] = new PParticle(x2, y2, physics); controls[0] = new PParticle(cx1, cy1, physics); controls[1] = new PParticle(cx2, cy2, physics); setupPoints(); selectedPoint = null; } Bezier(Bezier bezCurve) { this(); copyFrom(bezCurve); } void copyFrom(Bezier bezCurve) { anchors[0].set(bezCurve.anchors[0]); anchors[1].set(bezCurve.anchors[1]); controls[0].set(bezCurve.controls[0]); controls[1].set(bezCurve.controls[1]); } void copyTo(Bezier bezCurve) { bezCurve.anchors[0].set(anchors[0]); bezCurve.anchors[1].set(anchors[1]); bezCurve.controls[0].set(controls[0]); bezCurve.controls[1].set(controls[1]); } void setupPoints() { points = new PParticle[4]; points[0] = anchors[0]; points[1] = controls[0]; points[2] = controls[1]; points[3] = anchors[1]; } float getPointCoord(int n, int c) { return c == 0 ? points[n].x : points[n].y; } void setPointCoord(int n, int c, float v) { if (c == 0) points[n].x = v; else points[n].y = v; } void setPoint(int n, float x, float y) { points[n].set(x, y, 0); } void eval(PVector pt, float t) { evalCurve(pt, t); } void eval(int n, PVector pt, float t) { if (n == 0) evalCurve(pt, t); else if (n == 1) evalTangent(pt, t); else if (n == 2) evalAccel(pt, t); } void evalCurve(PVector pt, float t) { pt.x = bezierPoint(anchors[0].x, controls[0].x, controls[1].x, anchors[1].x, t); pt.y = bezierPoint(anchors[0].y, controls[0].y, controls[1].y, anchors[1].y, t); } void evalTangent(PVector pt, float t) { pt.x = bezierTangent(anchors[0].x, controls[0].x, controls[1].x, anchors[1].x, t); pt.y = bezierTangent(anchors[0].y, controls[0].y, controls[1].y, anchors[1].y, t); } void evalAccel(PVector pt, float t) { pt.x = bezierAccel(anchors[0].x, controls[0].x, controls[1].x, anchors[1].x, t); pt.y = bezierAccel(anchors[0].y, controls[0].y, controls[1].y, anchors[1].y, t); } float bezierAccel(float a, float b, float c, float d, float t) { return (6*t * (-a+3*b-3*c+d) + 6 * (a-2*b+c)); } void render(boolean showControls) { if (showControls) { stroke(255, 0, 0); line(anchors[0].x, anchors[0].y, controls[0].x, controls[0].y); line(controls[1].x, controls[1].y, anchors[1].x, anchors[1].y); } stroke(255); bezier(anchors[0].x, anchors[0].y, controls[0].x, controls[0].y, controls[1].x, controls[1].y, anchors[1].x, anchors[1].y); if (showControls) { for (int i = 0; i < 2; i++) { stroke(255); ellipse(anchors[i].x, anchors[i].y, 10, 10); stroke(255, 0, 0); ellipse(controls[i].x, controls[i].y, 10, 10); } } } boolean selectPoint(float x, float y, float r) { selectedPoint = null; PVector p = new PVector(x, y); for (int i = 0; i < 4; i++) if (points[i].dist(p) < r) { selectedPoint = points[i]; return true; } return false; } void setSelectedPoint(float x, float y) { if (selectedPoint != null) { selectedPoint.moveTo(x, y); } } void update() { for (int i = 0; i < 4; i++) points[i].update(); } void stopPhysics() { for (int i = 0; i < 4; i++) points[i].restart(physics); } PParticle[] points; PParticle[] anchors; PParticle[] controls; PParticle selectedPoint; }