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