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