Practical Coding in Java

Learn to write and validate your own code

Darren Kessner, PhD

(revised May 2026)

Previous: TimeComplexity

Phyllotaxis

This code example demonstrates spiral phyllotaxis, which is the growth pattern you can see in the leaves or petals of many types of plants (e.g. sunflowers, pinecones).

The pattern itself can be implemented simply with a list of balls. You can think of a launcher at the origin that propels a ball in a particular direction, and then rotates by a constant angle before launching the next ball. The spiral phyllotaxis pattern is generated by using the ‘golden angle’ for the angle of rotation. The golden angle is related to the golden ratio and the Fibonacci numbers. This pattern maximizes the space filled by the balls, and this is because the golden ratio is the “most irrational number” (in a precise mathematical sense). The pattern is found commonly in nature as a way of maximizing exposure to sunlight.

//
// Ball.java
//


import processing.core.*;


public class Ball
{
    public Ball(PApplet p, PVector velocity, int color)
    {
        this.p = p;
        this.position = new PVector();  // start at (0,0)
        this.velocity = velocity.copy();
        this.color = color;
    }

    public void display(PGraphics pg)
    {
        pg.fill(color);
        pg.noStroke();
        pg.ellipse(position.x, position.y, radius*2, radius*2);

        position.add(velocity);
        velocity.mult(.9985f);
    }

    public boolean isDead()
    {
        return position.mag() > 3000;
    }

    private PApplet p;
    private PVector position;
    private PVector velocity;
    private int color;

    private static final int radius = 40;
}
//
// Phyllotaxis.java
//


import processing.core.*;
import java.util.*;


public class Phyllotaxis extends PApplet
{
    public void settings()
    {
        size(600, 900);
        pixelDensity(1);
    }

    public void setup()
    {
        pg = createGraphics(1800, 2700);
        colorMode(HSB, 100);
        noCursor();
    }

    private void drawStuffOffscreen()
    {
        pg.beginDraw();
        pg.background(0);
        pg.translate(pg.width/2, pg.height/2);

        for (Ball b : balls)
            b.display(pg);

        pg.endDraw();
    }

    public void draw()
    {
        // draw everything to the offscreen buffer (pg), 
        // then display the buffer scaled to the screen size

        drawStuffOffscreen();
        image(pg, 0, 0, width, height);

        // add a new ball with the current direction and color

        currentAngle += goldenAngle;
        currentHue += .25;

        PVector currentVelocity = PVector.fromAngle(currentAngle);
        currentVelocity.setMag(5);

        int currentColor = color(currentHue%100, 100, 100, 150);

        balls.add(new Ball(this, currentVelocity, currentColor));

        // remove dead balls

        balls.removeIf(ball -> ball.isDead());
    }

    public void keyPressed()
    {
        if (key == 'n')
            noLoop();
        else if (key == 'l')
            loop();
        else if (key == 's')
        {
            println("Saving frame.");
            pg.save("phyllotaxis_cover.png");
        }
    }

    PGraphics pg;
    private ArrayList<Ball> balls = new ArrayList<Ball>();
    private float currentAngle = 0;
    private float currentHue = 0;

    private static final float phi = (float)(1 + Math.sqrt(5))/2; // Golden Ratio
    private static final float goldenAngleProportion = 1/phi/phi; // fraction of circle
    private static final float goldenAngle = 2*PI*goldenAngleProportion; // radians

    public static void main(String[] args)
    {
        println("goldenAngle: " + goldenAngle*180/PI + " degrees");
        PApplet.main("Phyllotaxis");
    }
}

Next: