Task: Sierpinski pentagon




Go: package main

import (
    "github.com/fogleman/gg"
    "image/color"
    "math"
)

var (
    red     = color.RGBA{255, 0, 0, 255}
    green   = color.RGBA{0, 255, 0, 255}
    blue    = color.RGBA{0, 0, 255, 255}
    magenta = color.RGBA{255, 0, 255, 255}
    cyan    = color.RGBA{0, 255, 255, 255}
)

var (
    w, h        = 640, 640
    dc          = gg.NewContext(w, h)
    deg72       = gg.Radians(72)
    scaleFactor = 1 / (2 + math.Cos(deg72)*2)
    palette     = [5]color.Color{red, green, blue, magenta, cyan}
    colorIndex  = 0
)

func drawPentagon(x, y, side float64, depth int) {
    angle := 3 * deg72
    if depth == 0 {
        dc.MoveTo(x, y)
        for i := 0; i < 5; i++ {
            x += math.Cos(angle) * side
            y -= math.Sin(angle) * side
            dc.LineTo(x, y)
            angle += deg72
        }
        dc.SetColor(palette[colorIndex])
        dc.Fill()
        colorIndex = (colorIndex + 1) % 5
    } else {
        side *= scaleFactor
        dist := side * (1 + math.Cos(deg72)*2)
        for i := 0; i < 5; i++ {
            x += math.Cos(angle) * dist
            y -= math.Sin(angle) * dist
            drawPentagon(x, y, side, depth-1)
            angle += deg72
        }
    }
}

func main() {
    dc.SetRGB(1, 1, 1) 
    dc.Clear()
    order := 5 
    hw := float64(w / 2)
    margin := 20.0
    radius := hw - 2*margin
    side := radius * math.Sin(math.Pi/5) * 2
    drawPentagon(hw, 3*margin, side, order-1)
    dc.SavePNG("sierpinski_pentagon.png")
}


Java: import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.geom.Path2D;
import static java.lang.Math.*;
import java.util.Random;
import javax.swing.*;

public class SierpinskiPentagon extends JPanel {
    
    final double degrees072 = toRadians(72);

    
    final double scaleFactor = 1 / (2 + cos(degrees072) * 2);

    final int margin = 20;
    int limit = 0;
    Random r = new Random();

    public SierpinskiPentagon() {
        setPreferredSize(new Dimension(640, 640));
        setBackground(Color.white);

        new Timer(3000, (ActionEvent e) -> {
            limit++;
            if (limit >= 5)
                limit = 0;
            repaint();
        }).start();
    }

    void drawPentagon(Graphics2D g, double x, double y, double side, int depth) {
        double angle = 3 * degrees072; 

        if (depth == 0) {

            Path2D p = new Path2D.Double();
            p.moveTo(x, y);

            
            for (int i = 0; i < 5; i++) {
                x = x + cos(angle) * side;
                y = y - sin(angle) * side;
                p.lineTo(x, y);
                angle += degrees072;
            }

            g.setColor(RandomHue.next());
            g.fill(p);

        } else {

            side *= scaleFactor;

            
            double distance = side + side * cos(degrees072) * 2;

            
            for (int i = 0; i < 5; i++) {
                x = x + cos(angle) * distance;
                y = y - sin(angle) * distance;
                drawPentagon(g, x, y, side, depth - 1);
                angle += degrees072;
            }
        }
    }

    @Override
    public void paintComponent(Graphics gg) {
        super.paintComponent(gg);
        Graphics2D g = (Graphics2D) gg;
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        int w = getWidth();
        double radius = w / 2 - 2 * margin;
        double side = radius * sin(PI / 5) * 2;

        drawPentagon(g, w / 2, 3 * margin, side, limit);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setTitle("Sierpinski Pentagon");
            f.setResizable(true);
            f.add(new SierpinskiPentagon(), BorderLayout.CENTER);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        });
    }
}

class RandomHue {
    
    final static double goldenRatioConjugate = (sqrt(5) - 1) / 2;
    private static double hue = Math.random();

    static Color next() {
        hue = (hue + goldenRatioConjugate) % 1;
        return Color.getHSBColor((float) hue, 1, 1);
    }
}