Task: Sierpinski curve




Go: package main

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

var (
    width  = 770.0
    height = 770.0
    dc     = gg.NewContext(int(width), int(height))
)

var cx, cy, h float64

func lineTo(newX, newY float64) {
    dc.LineTo(newX-width/2+h, height-newY+2*h)
    cx, cy = newX, newY
}

func lineN() { lineTo(cx, cy-2*h) }
func lineS() { lineTo(cx, cy+2*h) }
func lineE() { lineTo(cx+2*h, cy) }
func lineW() { lineTo(cx-2*h, cy) }

func lineNW() { lineTo(cx-h, cy-h) }
func lineNE() { lineTo(cx+h, cy-h) }
func lineSE() { lineTo(cx+h, cy+h) }
func lineSW() { lineTo(cx-h, cy+h) }

func sierN(level int) {
    if level == 1 {
        lineNE()
        lineN()
        lineNW()
    } else {
        sierN(level - 1)
        lineNE()
        sierE(level - 1)
        lineN()
        sierW(level - 1)
        lineNW()
        sierN(level - 1)
    }
}

func sierE(level int) {
    if level == 1 {
        lineSE()
        lineE()
        lineNE()
    } else {
        sierE(level - 1)
        lineSE()
        sierS(level - 1)
        lineE()
        sierN(level - 1)
        lineNE()
        sierE(level - 1)
    }
}

func sierS(level int) {
    if level == 1 {
        lineSW()
        lineS()
        lineSE()
    } else {
        sierS(level - 1)
        lineSW()
        sierW(level - 1)
        lineS()
        sierE(level - 1)
        lineSE()
        sierS(level - 1)
    }
}

func sierW(level int) {
    if level == 1 {
        lineNW()
        lineW()
        lineSW()
    } else {
        sierW(level - 1)
        lineNW()
        sierN(level - 1)
        lineW()
        sierS(level - 1)
        lineSW()
        sierW(level - 1)
    }
}

func squareCurve(level int) {
    sierN(level)
    lineNE()
    sierE(level)
    lineSE()
    sierS(level)
    lineSW()
    sierW(level)
    lineNW()
    lineNE() 
}

func main() {
    dc.SetRGB(0, 0, 1) 
    dc.Clear()
    level := 5
    cx, cy = width/2, height
    h = cx / math.Pow(2, float64(level+1))
    squareCurve(level)
    dc.SetRGB255(255, 255, 0) 
    dc.SetLineWidth(2)
    dc.Stroke()
    dc.SavePNG("sierpinski_curve.png")
}


Java: import java.io.*;

public class SierpinskiCurve {
    public static void main(final String[] args) {
        try (Writer writer = new BufferedWriter(new FileWriter("sierpinski_curve.svg"))) {
            SierpinskiCurve s = new SierpinskiCurve(writer);
            s.currentAngle = 45;
            s.currentX = 5;
            s.currentY = 10;
            s.lineLength = 7;
            s.begin(545);
            s.execute(rewrite(5));
            s.end();
        } catch (final Exception ex) {
            ex.printStackTrace();
        }
    }

    private SierpinskiCurve(final Writer writer) {
        this.writer = writer;
    }

    private void begin(final int size) throws IOException {
        write("<svg xmlns='http:
        write("<rect width='100%%' height='100%%' fill='white'/>\n");
        write("<path stroke-width='1' stroke='black' fill='none' d='");
    }

    private void end() throws IOException {
        write("'/>\n</svg>\n");
    }

    private void execute(final String s) throws IOException {
        write("M%g,%g\n", currentX, currentY);
        for (int i = 0, n = s.length(); i < n; ++i) {
            switch (s.charAt(i)) {
                case 'F':
                case 'G':
                    line(lineLength);
                    break;
                case '+':
                    turn(ANGLE);
                    break;
                case '-':
                    turn(-ANGLE);
                    break;
            }
        }
    }

    private void line(final double length) throws IOException {
        final double theta = (Math.PI * currentAngle) / 180.0;
        currentX += length * Math.cos(theta);
        currentY -= length * Math.sin(theta);
        write("L%g,%g\n", currentX, currentY);
    }

    private void turn(final int angle) {
        currentAngle = (currentAngle + angle) % 360;
    }

    private void write(final String format, final Object... args) throws IOException {
        writer.write(String.format(format, args));
    }

    private static String rewrite(final int order) {
        String s = AXIOM;
        for (int i = 0; i < order; ++i) {
            final StringBuilder sb = new StringBuilder();
            for (int j = 0, n = s.length(); j < n; ++j) {
                final char ch = s.charAt(j);
                if (ch == 'X')
                    sb.append(PRODUCTION);
                else
                    sb.append(ch);
            }
            s = sb.toString();
        }
        return s;
    }

    private final Writer writer;
    private double lineLength;
    private double currentX;
    private double currentY;
    private int currentAngle;

    private static final String AXIOM = "F--XF--F--XF";
    private static final String PRODUCTION = "XF+G+XF--F--XF+G+X";
    private static final int ANGLE = 45;
}