Tree.pde
// https://stackoverflow.com/questions/3522454/how-to-implement-a-tree-data-structure-in-java
// https://github.com/gt4dev/yet-another-tree-structure
class TreeNode<T extends AbstractShape> {
final int MAX_N = 8;
int N = 1;
T data;
TreeNode<T> parent;
ArrayList<TreeNode<T>> children;
TreeNode(T data) {
this.data = data;
this.children = new ArrayList<TreeNode<T>>();
}
private int findMinimumSquare(int n) {
for (int k = 1; k <= MAX_N; k++) {
if (n <= k * k) {
return k;
}
}
return MAX_N;
}
TreeNode<T> addChild(T child) {
TreeNode<T> childNode = new TreeNode<T>(child);
childNode.parent = this;
this.children.add(childNode);
this.N = findMinimumSquare(this.children.size());
return childNode;
}
boolean isRoot() {
return parent == null;
}
boolean isLeaf() {
return children.size() == 0;
}
int getLevel() {
if (this.isRoot()) {
return 0;
} else {
return parent.getLevel() + 1;
}
}
void draw() {
if (isLeaf()) {
data.draw();
} else {
for (int k = 0; k < children.size(); k++) {
int i = k % N;
int j = k / N;
pushMatrix();
translate(width / (float)N * j , height / (float)N * i);
scale(1.0 / N);
children.get(k).draw();
popMatrix();
}
}
}
}
TreeShape.pde
// http://blawat2015.no-ip.com/~mieki256/diary/201603202.html
final Comparator<PVector> comp = new Comparator<PVector>() {
int compare(PVector v1, PVector v2) {
if (v1.z > v2.z) return 1;
else if (v1.z == v2.z) return 0;
return -1;
}
};
abstract class AbstractShape {
abstract void draw();
}
class Circle extends AbstractShape {
void draw() {
rect(0, 0, width, height);
translate(width / 2.0, height / 2.0);
ellipse(0, 0, width, height);
}
}
class UFO extends AbstractShape {
color[] palette;
float angularVelocity = TWO_PI;
UFO(color[] palette) {
this(palette, TWO_PI*random(1.0, 2.0)*(random(1) > 0.5 ? 1.0 : -1.0));
}
UFO(color[] palette, float angularVelocity) {
this.palette = palette;
this.angularVelocity = angularVelocity;
}
void draw() {
float s = 0.6;
int nCircles = 6;
float w = width;
float h = height;
// noStroke();
rectMode(CENTER);
translate(width / 2.0, height / 2.0);
strokeWeight(0.8);
fill(palette[0]);
arc(0, 0, w*s, h*s, PI, TWO_PI);
PVector[] points = new PVector[nCircles];
float circleWidth = w / 3.0;
float angleInterval = TWO_PI / nCircles;
for (int k = 0; k < nCircles; k++) {
float phi = angleInterval * k;
float t = frameCount / 60.0 / TWO_PI;
float cx = (w / 2.0 - circleWidth / 2.0) * cos(t * angularVelocity + phi);
float cz = sin(t * angularVelocity + phi);
points[k] = new PVector(cx, 0, cz);
}
fill(palette[2]);
Arrays.sort(points, comp);
for (int k = 0; k < nCircles; k++) {
float cx = points[k].x;
arc(cx, h / 4.0, circleWidth, circleWidth, 0, PI);
}
fill(palette[1]);
beginShape();
vertex(w/2.0*s, 0);
vertex(w/2.0, h/4.0);
vertex(-w/2.0, h/4.0);
vertex(-w/2.0*s, 0);
endShape(CLOSE);
}
}
sketch_210221a.pde
import java.util.Arrays;
import java.util.Comparator;
TreeNode tree;
boolean recording = false;
void setup() {
size(800, 800);
frameRate(30);
tree = new TreeNode(new UFO(randomPalette()));
buildTree(tree, 0);
}
void draw() {
background(10, 10, 64);
tree.draw();
if (recording) {
saveFrame("frames/#####.png");
}
}
color[] randomPalette() {
color[][] palettes = new color[][] {
{color(#16C5F5), color(#F52F6E), color(#F5E52F)},
{color(#18F569), color(#9A32F5), color(#F5B249)},
{color(#B7F52F), color(#2F73F5), color(#F53816)},
};
int k = (int)random(palettes.length);
return palettes[k];
}
void buildTree(TreeNode t, int depth) {
if (depth != 0 && (random(10) < 3 || t.getLevel() >= 3)) {
t.addChild(new UFO(randomPalette()));
return;
}
int[] counts = {4, 9};
int n = counts[(int)random(counts.length)];
for (int k = 0; k < n; k++) {
TreeNode child = t.addChild(new UFO(randomPalette()));
buildTree(child, depth + 1);
}
}
void mousePressed() {
tree = new TreeNode(new UFO(randomPalette()));
buildTree(tree, 0);
redraw();
}
static final String timestamp(final String name, final String ext) {
return name + "-" + year() + nf(month(), 2) + nf(day(), 2) +
"-" + nf(hour(), 2) + nf(minute(), 2) + nf(second(), 2) + ext;
}
void keyReleased() {
// saveFrame(String.format("frames/%s", timestamp("Project", ".png")));
recording = !recording;
}