pythagoras.c

download raw

// Draw a pythagoras triangle with no trig calls
#include <math.h>
#include <stdio.h>

typedef float F;
#define M(name) (name ## f)
#define ZERO 0.f
#define ONE 1.f

#define MOVETO "moveto"
#define LINETO "lineto"
#define LINETO_CLOSEPATH_STROKE "lineto closepath stroke"

typedef struct { F a, b, c, d, e, f; } PSMatrix;

void matmul(PSMatrix *result, PSMatrix *m1, PSMatrix *m2) {
    PSMatrix r;
    r.a = m2->a * m1->a + m2->b * m1->c;
    r.b = m2->a * m1->b + m2->b * m1->d;
    r.c = m2->c * m1->a + m2->d * m1->c;
    r.d = m2->c * m1->b + m2->d * m1->d;
    r.e = m2->e * m1->a + m2->f * m1->c + m1->e;
    r.f = m2->e * m1->b + m2->f * m1->d + m1->f;
    *result = r;
}

F A = 4, B = 3, C;
F cos_theta, sin_theta;

// Each matrix moves from the old baseline [bottom of square] to the baseline of the square on the B or C side
// of the triangle.
PSMatrix toB, toC, identity = {ONE, ZERO, ZERO, ONE, ZERO, ZERO};

void make_matrix(PSMatrix *m, F x1, F y1, F x2, F y2) {
    F dx = x2-x1, dy = y2-y1;
    F ux = dx / C;
    F uy = dy / C;

    PSMatrix mm = { ux, uy, -uy, ux, x1, y1 };

    *m = mm;
}

void op_transformed(const char *op, PSMatrix *m, F x, F y) {
    F tx = m->a * x + m->c * y + m->e,
      ty = m->b * x + m->d * y + m->f;
    printf("%.1f %1.f %s\n", tx, ty, op);
}

void recurse(PSMatrix *m, int n) {
    op_transformed(MOVETO, m, 0, 0);
    op_transformed(LINETO, m, 0, C);
    op_transformed(LINETO, m, C, C);
    op_transformed(LINETO_CLOSEPATH_STROKE, m, C, 0);

    if (n > 0) {
        PSMatrix m1;
        matmul(&m1, m, &toB);
        recurse(&m1, n-1);
        matmul(&m1, m, &toC);
        recurse(&m1, n-1);
    }

}

int main() {
    C = M(sqrt)(A*A + B*B);
    F dy = A * B / C;
    F dx = M(sqrt)(A*A - dy*dy);
    make_matrix(&toB, 0, C, dx, C+dy);
    make_matrix(&toC, dx, C+dy, C, C);

    fprintf(stderr, "% 6.2f % 6.2f % 6.2f\n% 6.2f % 6.2f % 6.2f\n\n",
            toB.a, toB.b, toB.c,
            toB.d, toB.e, toB.f);
    fprintf(stderr, "% 6.2f % 6.2f % 6.2f\n% 6.2f % 6.2f % 6.2f\n\n",
            toC.a, toC.b, toC.c,
            toC.d, toC.e, toC.f);

    PSMatrix initial = {ONE * 72 / 8, ZERO, ZERO, ONE*72 / 8, ONE*72*3, ONE*8};

    recurse(&initial, 6);
    printf("showpage\n");
}