Task: Sierpinski curve


C++: 
#include <cmath>
#include <fstream>
#include <iostream>
#include <string>

class sierpinski_curve {
public:
    void write(std::ostream& out, int size, int length, int order);
private:
    static std::string rewrite(const std::string& s);
    void line(std::ostream& out);
    void execute(std::ostream& out, const std::string& s);
    double x_;
    double y_;
    int angle_;
    int length_;
};

void sierpinski_curve::write(std::ostream& out, int size, int length, int order) {
    length_ = length;
    x_ = length/std::sqrt(2.0);
    y_ = 2 * x_;
    angle_ = 45;
    out << "<svg xmlns='http:
        << size << "' height='" << size << "'>\n";
    out << "<rect width='100%' height='100%' fill='white'/>\n";
    out << "<path stroke-width='1' stroke='black' fill='none' d='";
    std::string s = "F--XF--F--XF";
    for (int i = 0; i < order; ++i)
        s = rewrite(s);
    execute(out, s);
    out << "'/>\n</svg>\n";
}

std::string sierpinski_curve::rewrite(const std::string& s) {
    std::string t;
    for (char c : s) {
        if (c == 'X')
            t += "XF+G+XF--F--XF+G+X";
        else
            t += c;
    }
    return t;
}

void sierpinski_curve::line(std::ostream& out) {
    double theta = (3.14159265359 * angle_)/180.0;
    x_ += length_ * std::cos(theta);
    y_ -= length_ * std::sin(theta);
    out << " L" << x_ << ',' << y_;
}

void sierpinski_curve::execute(std::ostream& out, const std::string& s) {
    out << 'M' << x_ << ',' << y_;
    for (char c : s) {
        switch (c) {
        case 'F':
        case 'G':
            line(out);
            break;
        case '+':
            angle_ = (angle_ + 45) % 360;
            break;
        case '-':
            angle_ = (angle_ - 45) % 360;
            break;
        }
    }
}

int main() {
    std::ofstream out("sierpinski_curve.svg");
    if (!out) {
        std::cerr << "Cannot open output file\n";
        return 1;
    }
    sierpinski_curve s;
    s.write(out, 545, 7, 5);
    return 0;
}



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")
}