// Draw a pythagoras triangle with no trig calls #include #include 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"); }