typedef int xT; /* x coordinate */
typedef int yT; /* y coordinate */
#define pmWd ((xT)2000)
#define pmHg ((yT)2000)
#define pmX0 ((xT)pmWd/2)
#define pmY0 ((yT)pmHg/2)
static Pixmap pm;
static GC gcBlack;
static GC gcWhite;
static GC gcGrey;
static inline void rotatePoint(
xT *xd,
yT *yd,
double al,
xT xs,
yT ys)
{
double const s = sin(al);
double const c = cos(al);
*xd = (xT)(xs * c - ys * s);
*yd = (yT)(xs * s + ys * c);
}
static inline void doPinnaCircles(void)
{
/* circle radiuses */
double const rMin = 300.0;
double const rInc = 200.0;
double const rMax = 950;
double r;
/* square side length */
double const S = 100.0;
double const s = S * 0.7;
double alInc = 2 * M_PI * 15 / 360;
int i;
XFillRectangle(dpy,pm,gcGrey,0,0,pmWd,pmHg);
for (r=rMin; r <=rMax; r+=rInc) {
/* currect radius such that an integer multiple of squares fits */
double const p = 2.0 * M_PI * r;
int const cnt = floor(p/S/2.0) * 2;
double const pc = cnt * S;
xT const rc = (xT)(pc / 2.0 / M_PI);
alInc = - alInc;
for (i=0; i<cnt; i+=1) {
/* angle to midpoint of i.th square */
double const Al = 2.0 * M_PI * i / cnt;
/* mid point of i.th square */
xT const xx = pmX0 + (xT)(sin(Al) * rc);
yT const yy = pmY0 + (yT)(cos(Al) * rc);
/* edge angle of i.th square */
double const al = Al + alInc;
xT xa, xb, xc, xd;
yT ya, yb, yc, yd;
rotatePoint(&xa,&ya,-al,+s/2.0,+s/2.0);
rotatePoint(&xb,&yb,-al,-s/2.0,+s/2.0);
rotatePoint(&xc,&yc,-al,-s/2.0,-s/2.0);
rotatePoint(&xd,&yd,-al,+s/2.0,-s/2.0);
GC const gc = (i % 2 == 0 ? gcWhite : gcBlack);
XDrawLine(dpy,pm,gc,xx+xa,yy+ya,xx+xb,yy+yb);
XDrawLine(dpy,pm,gc,xx+xb,yy+yb,xx+xc,yy+yc);
XDrawLine(dpy,pm,gc,xx+xc,yy+yc,xx+xd,yy+yd);
XDrawLine(dpy,pm,gc,xx+xd,yy+yd,xx+xa,yy+ya);
}
}
XImage * const im = XGetImage(dpy,pm,0,0,pmWd,pmHg,-1,ZPixmap);
writePpmFile(stdout,"",im); /* library function to print XImage to FILE*, code not included here */
}
/* main() initializes Pixmap pm, and GC gcBlack, gcWhite, gcGrey using library functions, then calls doPinnaCircles(), code not included here */