/* in this version the annoyingly large 16 lines following const double comb[4][4] multiply two matrices togather. As it stands, multiplying rotz by movxy, the resulting matrix comp performs a small rotation around z and a small movement in a single step. You can combine any two of the matrices in this way, but you need to be careful to replace all 16 appearances of rotz with one matrix and all 16 appearances of movxy with the other. Best to let visual studio do a "replace all" (on a selection, not on the whole file) The sixteen lines should ideally become a single function call, they really don't belong in main. But due to a deficiency in C++, you can't write a function that returns an array (or matrix) without getting into complexities that do not belong in this class */ #include "library.h" const int winsize = 500; const int halfwinsize = winsize / 2; double matvecmul(const double m[4][4], const double v[4], const int i, const int p) { if (p == 4) return 0.0; return m[i][p] * v[p] + matvecmul(m, v, i, p + 1); } double matvecmul(const double m[4][4], const double v[4], const int i) { return matvecmul(m, v, i, 0); } double matmatmul(const double m1[4][4], const double m2[4][4], const int i, const int j, const int p) { if (p == 4) return 0.0; return m1[i][p] * m2[p][j] + matmatmul(m1, m2, i, j, p + 1); } double matmatmul(const double m1[4][4], const double m2[4][4], const int i, const int j) { return matmatmul(m1, m2, i, j, 0); } const double pi = acos(-1.0); double degrees(const double x) { return x * pi / 180.0; } void move_to(const double p[4]) { move_to(halfwinsize + p[0], halfwinsize - p[1]); } void draw_to(const double p[4]) { draw_to(halfwinsize + p[0], halfwinsize - p[1]); } void animate(const double m[4][4], const double v[4], const int nsteps) { if (nsteps == 0) return; const double rotated[4] = { matvecmul(m, v, 0), matvecmul(m, v, 1), matvecmul(m, v, 2), matvecmul(m, v, 3) }; const double centre[4] = { 0, 0, 0, 1 }; const int c = get_pen_color(); move_to(centre); draw_to(rotated); wait(0.01); set_pen_color(color::white); move_to(centre); draw_to(rotated); set_pen_color(c); animate(m, rotated, nsteps - 1); } void main() { make_window(winsize, winsize); set_pen_width(3); const double rotz[4][4] = { { cos(degrees(1)), sin(degrees(1)), 0, 0 }, { -sin(degrees(1)), cos(degrees(1)), 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; const double roty[4][4] = { { cos(degrees(1)), 0, sin(degrees(1)), 0 }, { 0, 1, 0, 0 }, { -sin(degrees(1)), 0, cos(degrees(1)), 0 }, { 0, 0, 0, 1 } }; const double rotx[4][4] = { { 1, 0, 0, 0 }, { 0, cos(degrees(1)), sin(degrees(1)), 0 }, { 0, -sin(degrees(1)), cos(degrees(1)), 0 }, { 0, 0, 0, 1 } }; const double grow[4][4] = { { 1.01, 0, 0, 0 }, { 0, 1.01, 0, 0 }, { 0, 0, 1.01, 0 }, { 0, 0, 0, 1 } }; const double shrink[4][4] = { { 0.98, 0, 0, 0 }, { 0, 0.98, 0, 0 }, { 0, 0, 0.98, 0 }, { 0, 0, 0, 1 } }; const double movx[4][4] = { { 1, 0, 0, 0.5 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; const double movxy[4][4] = { { 1, 0, 0, 2 }, { 0, 1, 0, -2 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; const double comb[4][4] = { { matmatmul(rotz, movxy, 0, 0), matmatmul(rotz, movxy, 0, 1), matmatmul(rotz, movxy, 0, 2), matmatmul(rotz, movxy, 0, 3) }, { matmatmul(rotz, movxy, 1, 0), matmatmul(rotz, movxy, 1, 1), matmatmul(rotz, movxy, 1, 2), matmatmul(rotz, movxy, 1, 3) }, { matmatmul(rotz, movxy, 2, 0), matmatmul(rotz, movxy, 2, 1), matmatmul(rotz, movxy, 2, 2), matmatmul(rotz, movxy, 2, 3) }, { matmatmul(rotz, movxy, 3, 0), matmatmul(rotz, movxy, 3, 1), matmatmul(rotz, movxy, 3, 2), matmatmul(rotz, movxy, 3, 3) } }; const double line[4] = { 50, 150, 150, 1 }; set_pen_color(color::red); animate(comb, line, 360); }