/* make an icosahedron
 *
 * The Clever Fact is: you can make a dodecahedron by starting with a cube
 * and putting a "tent" on top of each face. The tent needs to have "height"
 * (root5-1)/2, and "offset" the square of that.
 *
 * And the icosahedron is the dual of the dodecahedron.
 * This program is very similar to dodec.c .
 */

#include <math.h>
#include <stdio.h>

#define HEIGHT	0.61803398875
#define OFFSET	0.38196601125	/* HEIGHT^2 */
#define BIG	(1+HEIGHT)
#define SMALL	(1-OFFSET)

#define DISTANCE 30	/* was 10 */

#define FACES 12

#undef LABEL

typedef double point[3];

/* vertices of dodecahedron */
point v[20] = {
	/* vertices of cube */
  { -1,-1,-1 },	/* 0 */
  { -1,-1, 1 },	/* 1 */
  { -1, 1,-1 },	/* 2 */
  { -1, 1, 1 },	/* 3 */
  {  1,-1,-1 },	/* 4 */
  {  1,-1, 1 },	/* 5 */
  {  1, 1,-1 },	/* 6 */
  {  1, 1, 1 },	/* 7 */
  { -SMALL, 0, -BIG },	/* 8 */
  {  SMALL, 0, -BIG },	/* 9 */
  { -SMALL, 0,  BIG },	/* 10 */
  {  SMALL, 0,  BIG },	/* 11 */
  { 0, -BIG, -SMALL },	/* 12 */
  { 0, -BIG,  SMALL },	/* 13 */
  { 0,  BIG, -SMALL },	/* 14 */
  { 0,  BIG,  SMALL },	/* 15 */
  { -BIG, -SMALL, 0 },	/* 16 */
  { -BIG,  SMALL, 0 },	/* 17 */
  {  BIG, -SMALL, 0 },	/* 18 */
  {  BIG,  SMALL, 0 },	/* 19 */
};

/* faces of dodecahedron */
/* this is an arbitrary order */
int faces[FACES][5] = {
  {0,12,13,1,16},
  {4,12,13,5,18},
  {0,16,17,2,8},
  {6,9,4,18,19},
  {0,8,9,4,12},
  {2,14,6,9,8},
  {1,13,5,11,10},
  {3,10,11,7,15},
  {1,10,3,17,16},
  {5,18,19,7,11},
  {2,17,3,15,14},
  {6,14,15,7,19}
};

/* will contain vertices of icosahedron */
point w[12];

/* will contain faces of icosahedron */
int f[20][3];
int nv[20];	/* how many vertices of this face so far? */

/* output vertex w[n], converted to 2d */
void wrvx(int n) {
  printf("%.4lg %.4lg",(DISTANCE-1)*100*w[n][0]/(w[n][2]+DISTANCE)+200,
                       (DISTANCE-1)*100*w[n][1]/(w[n][2]+DISTANCE)+200);
}

/* output points for face f[n] */
void facepath(int n) {
  int i;
  printf("  Move "); wrvx(f[n][0]);
  for (i=1;i<3;++i) {
    printf("\n  Line "); wrvx(f[n][i]); }
  printf("\n  Close\n");
}

/* is face n visible from 0,0,-5 ? */
int visible(int n) {
  double x=0,y=0,z=0;
  int i;
  for (i=0;i<3;++i) {
    x+=w[f[n][i]][0];
    y+=w[f[n][i]][1];
    z+=w[f[n][i]][2];
  }
  x/=3; y/=3; z/=3;
  return (x*x+y*y+(z+DISTANCE)*z<0);
}

int main(int ac, char *av[]) {
  int i;
  double ax,ay,az;
  if (ac!=4) {
    fprintf(stderr,"Usage: icos angleX angleY angleZ\n");
    return 0;
  }
  sscanf(av[1],"%lf",&ax); ax*=3.141592653589793/180;
  sscanf(av[2],"%lf",&ay); ay*=3.141592653589793/180;
  sscanf(av[3],"%lf",&az); az*=3.141592653589793/180;
	/* set up vertex and face arrays for icos from those for dodec */
  { double x,y,z; int j; int n;
    for (i=0;i<12;++i) {
      x=0; y=0; z=0;
      for (j=0;j<5;++j) {
        n=faces[i][j];
        x+=v[n][0];
        y+=v[n][1];
        z+=v[n][2];
        f[n][nv[n]++]=i;
      }
      w[i][0]=x/5; w[i][1]=y/5; w[i][2]=z/5;
    }
  }
  { double cx=cos(ax),sx=sin(ax),cy=cos(ay),sy=sin(ay),cz=cos(az),sz=sin(az);
    double t,x,y,z;
    for (i=0;i<12;++i) {
      x=w[i][0]; y=w[i][1]; z=w[i][2];
      t=x; x=x*cz-y*sz; y=t*sz+y*cz;
      t=x; x=x*cy-z*sy; z=t*sy+z*cy;
      t=y; y=y*cx-z*sx; z=t*sx+z*cx;
      w[i][0]=x; w[i][1]=y; w[i][2]=z;
    }
  }
#ifdef LABEL
  printf("FontTable {\n  1 Trinity.Medium\n}\n");
  for (i=0;i<12;++i) {
    printf("\nText {\n  Style 1\n  Size 12 12\n  StartAt "); wrvx(i);
    printf("\n  Text %d\n}\n",i);
  }
#endif
  printf("\nPath {\n");
  for (i=0;i<20;++i) {
    if (visible(i)) facepath(i);
  }
  printf("}\n\nPath {\n  Style { Dash { 1 4 } }\n");
  for (i=0;i<20;++i){
    if (!visible(i)) facepath(i);
  }
  printf("}\n");
  return 0;
}
