Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* -*- mode: java; indent-tabs-mode; nil -*- */
- int canvasWidth = 500;
- int canvasHeight = 500;
- ControlPoint[] controlPoints;
- CheckBox chkShowControlPoints;
- Setaria setaria;
- void setup() {
- frameRate(16);
- size(canvasWidth, canvasHeight);
- controlPoints = new ControlPoint[4];
- controlPoints[0] = new ControlPoint(400, 520, 32);
- controlPoints[1] = new ControlPoint(480, 400, 32);
- controlPoints[2] = new ControlPoint(200, 64, 32);
- controlPoints[3] = new ControlPoint(64, 64, 32);
- for (int i = 0; i < controlPoints.length; i++) {
- controlPoints[i].setRange(controlPoints[i].x - 100,
- 50,
- controlPoints[i].x + 100,
- 550);
- }
- chkShowControlPoints = new CheckBox(8, 8, 32, "Show Control Points", true);
- setaria = new Setaria(controlPoints);
- update();
- }
- void draw() {
- update();
- background(#193608);
- int currentTimeSec = millis() / 1000;
- strokeWeight(3);
- stroke(255);
- noFill();
- if (chkShowControlPoints.value) {
- for (int i = 0; i < controlPoints.length; i++) {
- controlPoints[i].draw();
- }
- }
- chkShowControlPoints.draw();
- setaria.draw();
- }
- void update() {
- int mx = mouseX;
- int my = mouseY;
- for (int i = 0; i < controlPoints.length; i++) {
- controlPoints[i].track(mx, my);
- }
- setaria.update();
- }
- void mousePressed() {
- for (int i = 0; i < controlPoints.length; i++) {
- controlPoints[i].mousePressed();
- }
- chkShowControlPoints.mousePressed();
- }
- void mouseReleased() {
- for (int i = 0; i < controlPoints.length; i++) {
- controlPoints[i].mouseReleased();
- }
- }
- interface Drawable {
- void draw();
- }
- class Point implements Drawable {
- int x;
- int y;
- Point(int x, int y) {
- moveTo(x, y);
- }
- void moveTo(int x, int y) {
- this.x = x;
- this.y = y;
- }
- void add(int dx, int dy) {
- this.x += dx;
- this.y += dy;
- }
- void add(Point pt) {
- add(pt.x, pt.y);
- }
- void scalar(float f) {
- this.x *= f;
- this.y *= f;
- }
- void draw() {
- point(this.x, this.y);
- }
- }
- class ControlPoint implements Drawable {
- int left;
- int top;
- int right;
- int bottom;
- int x;
- int y;
- int radius;
- boolean dragging;
- ControlPoint(int x, int y, int r) {
- setRange(x, y, x, y);
- moveTo(x, y);
- this.radius = r;
- this.dragging = false;
- }
- void setRange(int left, int top, int right, int bottom) {
- this.left = left;
- this.top = top;
- this.right = right;
- this.bottom = bottom;
- moveTo(this.x, this.y);
- }
- boolean isBusy() {
- return (this.isMouseOver() || this.dragging);
- }
- boolean isMouseOver() {
- int mx = mouseX;
- int my = mouseY;
- int dx = this.x - mx;
- int dy = this.y - my;
- return (dx * dx + dy * dy <= this.radius * this.radius);
- }
- void mousePressed() {
- this.dragging = isMouseOver();
- }
- void mouseReleased() {
- this.dragging = false;
- }
- void moveTo(int x, int y) {
- if (x < this.left) {
- x = this.left;
- } else if (x >= this.right) {
- x = this.right;
- }
- if (y < this.top) {
- y = this.top;
- } else if (y >= this.bottom) {
- y = this.bottom;
- }
- this.x = x;
- this.y = y;
- }
- void track(int mx, int my) {
- if (this.dragging) {
- moveTo(mx, my);
- }
- }
- void draw() {
- noFill();
- int alpha = abs((millis() % 2000) - 1000) / 1000 * 255;
- stroke(255, alpha);
- ellipse(this.x, this.y, this.radius, this.radius);
- }
- }
- class Setaria implements Drawable {
- Point[] stemPoints;
- ControlPoint[] controlPoints;
- Setaria(ControlPoint[] controlPoints) {
- this.controlPoints = controlPoints;
- this.stemPoints = new Point[7];
- for (int i = 0; i < stemPoints.length; i++) {
- this.stemPoints[i] = new Point(0, 0);
- }
- update(6);
- }
- void update(int dw) {
- int w = dw * 3;
- for (int i = 0; i < 3; i++) {
- int j = i;
- if (i > 0) j = i - 1;
- int dx = controlPoints[j].y - controlPoints[i + 1].y;
- int dy = controlPoints[i + 1].x - controlPoints[j].x;
- float r = w / sqrt(dx*dx + dy*dy);
- stemPoints[i].moveTo(controlPoints[i].x, controlPoints[i].y);
- stemPoints[i].add(r*dx, r*dy);
- dx *= -1;
- dy *= -1;
- stemPoints[6 - i].moveTo(controlPoints[i].x, controlPoints[i].y);
- stemPoints[6 - i].add(r*dx, r*dy);
- w -= dw;
- }
- stemPoints[3].moveTo(controlPoints[3].x, controlPoints[3].y);
- }
- void draw() {
- drawStem(6, #629a37);
- drawSpikes();
- }
- void drawStem(int dw, color c) {
- update(dw);
- strokeWeight(1);
- stroke(c);
- fill(c);
- beginShape();
- vertex(stemPoints[0].x, stemPoints[0].y);
- bezierVertex(stemPoints[1].x, stemPoints[1].y,
- stemPoints[2].x, stemPoints[2].y,
- stemPoints[3].x, stemPoints[3].y);
- bezierVertex(stemPoints[4].x, stemPoints[4].y,
- stemPoints[5].x, stemPoints[5].y,
- stemPoints[6].x, stemPoints[6].y);
- endShape(CLOSE);
- }
- void drawSpikes() {
- update(6);
- drawSpikes(stemPoints[0].x, stemPoints[0].y,
- stemPoints[1].x, stemPoints[1].y,
- stemPoints[2].x, stemPoints[2].y,
- stemPoints[3].x, stemPoints[3].y,
- 20, 60, 60, 90, 40);
- drawSpikes(stemPoints[3].x, stemPoints[3].y,
- stemPoints[4].x, stemPoints[4].y,
- stemPoints[5].x, stemPoints[5].y,
- stemPoints[6].x, stemPoints[6].y,
- 0, 40, 60, 40, 90);
- }
- void drawSpikes(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4,
- int start, int end, int count, int w1, int w2) {
- randomSeed(0);
- for (int i = start; i <= end; i++) {
- float t = (float)i / count;
- float weight = w1 + (w2 - w1)*t;
- float x = bezierPoint(x1, x2, x3, x4, t);
- float y = bezierPoint(y1, y2, y3, y4, t);
- float tx = bezierTangent(x1, x2, x3, x4, t);
- float ty = bezierTangent(y1, y2, y3, y4, t);
- float tr = sqrt(tx*tx + ty*ty);
- float dx = random(16) - 8;
- float dy = random(16) - 8;
- x += dx;
- y += dy;
- strokeWeight(16);
- stroke(#d0f0a7, 128);
- point(x, y);
- strokeWeight(1);
- stroke(#d9f1c3, 64);
- int n = 50;
- for (int j = 0; j < n; j++) {
- float r = weight + random(weight / 2);
- float cs = - ty / tr;
- float sn = tx / tr;
- float angle = radians(random(120) - 60);
- float cs2 = cos(angle);
- float sn2 = sin(angle);
- cs = cs*cs2 - sn*sn2;
- sn = sn*cs2 + cs*sn2;
- line(x, y, x + cs*r, y + sn*r);
- }
- }
- }
- }
- class CheckBox implements Drawable {
- int left;
- int top;
- int height;
- String caption;
- boolean value;
- PFont font;
- CheckBox(int x, int y, int h, String caption, boolean initialValue) {
- this.left = x;
- this.top = y;
- this.height = h;
- this.value = initialValue;
- this.caption = caption;
- this.font = loadFont(PFont.list()[0], this.height);
- }
- boolean isMouseOver() {
- int mx = mouseX;
- int my = mouseY;
- return ((mx >= this.left) && (mx < this.left + this.height) &&
- (my >= this.top) && (my < this.top + this.height));
- }
- void mousePressed() {
- if (this.isMouseOver()) {
- this.value = !this.value;
- }
- }
- void draw() {
- stroke(#80c060);
- strokeWeight(4);
- noFill();
- rect(this.left, this.top, this.height, this.height);
- fill(#80c060);
- textFont(this.font);
- textAlign(LEFT, BOTTOM);
- text(this.caption, this.left + this.height * 1.2, this.top + this.height);
- if (this.value) {
- line(this.left, this.top + this.height / 2,
- this.left + this.height * 1 / 3, this.top + this.height);
- line(this.left + this.height * 1 / 3, this.top + this.height,
- this.left + this.height, this.top);
- }
- }
- }
Add Comment
Please, Sign In to add comment