The only thing complicated amongst the REC definitions is the scheme for reflecting a polygon in one of its edges. To begin with, the formula for a line between two points (x1,y1) and (x2,y2) in a plane is conveniently written in in the form
(x2 - x1) y = (y2 - y1) x + (y1 x2 - y2 x1).
Matrixwise, the formula for reflecting the point (x0,y0) in the line
a x + b y + c = 0 is
These two formulas have been transcribed into C and coded into the function refen(n), which consults the list of vertices of the current polygon to get edge n to perform the reflection.
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* definition of REC operators and predicates */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ int rec(z) char *z; {if (rec_c(z,rprg,PLEN,dtbl)==1) rec_x(rprg);} void ropln() {edge--; refen((edge+pgon) % pgon);} /* reflect in last edge */ void roplo() {int i; /* offset the polygon */ for (i=0; i<pgon; i++) pointbase[i][0]=pointbase[i][0]/pointbase[i][2]+20.0; pointbase[i][1]=pointbase[i][1]/pointbase[i][2]; pointbase[i][2]=1.0; } void roplp() { /* pop fpolygon */ if (plev<0) return; roplo(); plev--; } void ropuc() {int i; /* draw polygon */ PSsetgray(NX_BLACK); PSmoveto(pointbase[pgon-1][0]/pointbase[pgon-1][2]+exoff, pointbase[pgon-1][1]/pointbase[pgon-1][2]+wyoff); for (i=0; i<pgon; i++) { PSlineto(pointbase[i][0]/pointbase[i][2]+exoff, pointbase[i][1]/pointbase[i][2]+wyoff);} } void ropuk() {int i, j; /* turn 60 deg right */ pgon = 3; edge = 0; for (i=0; i<pgon; i++) for (j=0; j<3; j++) pointbase[i][j] = isosrt[i][j]; } void ropul() {int i, j; /* turn 60 deg right */ pgon = 3; edge = 0; for (i=0; i<pgon; i++) for (j=0; j<3; j++) pointbase[i][j] = halftr[i][j]; } void ropun() {edge++; refen(edge % pgon);} /* reflect in next edge */ void ropuo() {int i, j; /* read top polygon */ for (i=0; i<pgon; i++) for (j=0; j<3; j++) pointbase[i][j]=polystack[plev][i][j]; } void ropup() {int i, j; /* push polygon */ plev++; if (plev>=HMAX) return; for (i=0; i<pgon; i++) for (j=0; j<3; j++) polystack[plev][i][j]=pointbase[i][j]; } void refen(nn) int nn; { /* reflect in edge n */ int i, m, n; double aa, bb, cc, x, y, ex1, ex2, wy1, wy2, rr, m11, m12, m21, m22; n = nn % pgon; m = (n + 1) % pgon; ex1 = pointbase[n][0]/pointbase[n][2]; ex2 = pointbase[m][0]/pointbase[m][2]; wy1 = pointbase[n][1]/pointbase[n][2]; wy2 = pointbase[m][1]/pointbase[m][2]; aa = wy1 - wy2; bb = ex2 - ex1; cc = wy2 * ex1 - wy1 * ex2; rr = aa * aa + bb * bb; m11 = bb * bb - aa * aa; m12 = -2.0 * aa * bb; m21 = m12; m22 = -m11; for (i=0; i<pgon; i++) { x = (m11 * pointbase[i][0] + m12 * pointbase[i][1]) /pointbase[i][2]; y = (m21 * pointbase[i][0] + m22 * pointbase[i][1]) /pointbase[i][2]; pointbase[i][0] = (x - 2.0 * aa * cc)/rr; pointbase[i][1] = (y - 2.0 * bb * cc)/rr; pointbase[i][2] = 1.0; } } void ropur() {int n; /* reflect in edge n */ n = *r_pc++ - '0'; if (n < 0 || n > pgon-1) return; else {edge=n; refen(n);}; } void roput() {int i, j; /* rhombus */ pgon = 4; edge = 0; for (i=0; i<pgon; i++) for (j=0; j<3; j++) pointbase[i][j]=rhombus[i][j]; } void ropuu() {int i, j; /* snubsquare */ pgon = 5; edge = 0; for (i=0; i<pgon; i++) for (j=0; j<3; j++) pointbase[i][j]=snubsq[i][j]; } void ropux() {int c, i; double th, dth; /* regular polygon */ c = *r_pc++ - '0'; if (c < 1 || c > 12) return; pgon = c; edge = pgon-1; dth = (2 * PI)/((double)(pgon)); for (i=0, th=-0.5*dth; i<pgon; i++, th+=dth) { pointbase[i][0] = cos(th); pointbase[i][1] = sin(th); pointbase[i][2] = 1.0/scale; } }