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

#define MAX_PIECES 36
#define AMB 0.3
#define IOR 0.0
#define RFL 0.6
#define RFR 0.0
#define DIF 0.0
#define UP 1
#define DOWN 2

struct vector
  {
  float x, y, z;
  };

FILE *output_file;

main()
{
  float start_x, start_y, start_z, radius;
  int number_pieces, num_stars;
  void build_primary_hull(), build_propulsion_units(), build_secondary_hull(),
       stars();
    
  printf("enter start_x --> ");
  scanf("%f", &start_x);
  printf("enter start_y --> ");
  scanf("%f", &start_y);
  printf("enter start_z --> ");
  scanf("%f", &start_z);
  printf("enter number of sections for each cylinder--> ");
  scanf("%d", &number_pieces);
  printf("enter radius of primary hull --> ");
  scanf("%f", &radius);
  printf("how many stars you want --> ");
  scanf("%d", &num_stars);
  output_file = fopen("enterprise.dat", "w");

  printf("building primary hull\n");
  fprintf(output_file, "\*_building_primary_hull\n");
  build_primary_hull(start_x, start_y, start_z, number_pieces, radius);
  fprintf(output_file, "\*_finished_building_primary_hull\n");

  fprintf(output_file, "\*_building_propulsion_units\n");
  build_propulsion_units(start_x, start_y, start_z, number_pieces, radius);
  fprintf(output_file, "\*_building_second_prop_unit\n");
  build_propulsion_units(start_x, start_y, start_z - 1.5 * radius, 
                         number_pieces, radius);
  fprintf(output_file, "\*_finished_building_propulsion_units\n");

  fprintf(output_file, "\*_building_secondary_hull\n");
  build_secondary_hull(start_x, start_y, start_z, number_pieces, radius);
  fprintf(output_file, "\*_finished_building_secondary_hull\n");
/*
  build_deflector(start_x, start_y, start_z, number_pieces, radius);
*/

  stars(num_stars, start_x, start_y, start_z);
  fclose(output_file);
} /* end of build enterprise */

void build_arc(start_angle, end_angle, center_pt1, center_pt2, radius,
               pt1, pt2, count, number_pieces)
float start_angle, end_angle, center_pt1, center_pt2, radius, pt1[], pt2[];
int count, number_pieces;

{
float increment, angle, step;

  step = number_pieces - count;
  increment = (end_angle - start_angle) / step;
  angle = start_angle;
  while (count <= step - 1)
    {
    pt1[count] = center_pt1 + (sin ( (double) ((angle * 6.2874) / 360.0)) 
                   * radius);
    pt2[count] = center_pt2 + (cos ( (double) ((angle * 6.2874) / 360.0))
                   * radius);
    angle += increment;
    count++;
    } /* end of while */
} /* end of build_arc */

void print_circle(center_x, center_y, center_z, circle, number_pieces, type)
float center_x, center_y, center_z;
struct vector circle[];
int number_pieces, type;
{
  int i;
  if (type == UP)
    {
    for (i = 0; i < number_pieces - 1; i++)
      {
                  /* circle */
      fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
         IOR, RFR, RFL, DIF, AMB, 
         center_x, center_y, center_z,
         circle[i].x, circle[i].y, circle[i].z,
         circle[i + 1].x, circle[i + 1].y, circle[i + 1].z);  
      }
      fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
         IOR, RFR, RFL, DIF, AMB, 
         center_x, center_y, center_z,
         circle[number_pieces - 1].x, circle[number_pieces - 1].y, circle[number_pieces - 1].z,
         circle[0].x, circle[0].y, circle[0].z);  
    } /* end of if type == UP */
  else
    {
    for (i = 0; i < number_pieces - 1; i++)
      {
                  /* circle */
      fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
         IOR, RFR, RFL, DIF, AMB, 
         center_x, center_y, center_z,
         circle[i + 1].x, circle[i + 1].y, circle[i + 1].z,
         circle[i].x, circle[i].y, circle[i].z);  
      }
      fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
         IOR, RFR, RFL, DIF, AMB, 
         center_x, center_y, center_z,
         circle[0].x, circle[0].y, circle[0].z,
         circle[number_pieces - 1].x, circle[number_pieces - 1].y, 
         circle[number_pieces - 1].z);
    }
}  /* end of print_circle */

void print_rectangles(front, back, number_pieces)
struct vector front[], back[];
int number_pieces;

{
  int i;

  for (i = 0; i < number_pieces - 1; i++)
    {
    fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
      IOR, RFR, RFL, DIF, AMB, 
      back[i+1].x, back[i+1].y, back[i+1].z,
      back[i].x, back[i].y, back[i].z,
      front[i + 1].x, front[i + 1].y, front[i + 1].z);
    fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
      IOR, RFR, RFL, DIF, AMB, 
      back[i].x, back[i].y, back[i].z,
      front[i].x, front[i].y, front[i].z,
      front[i + 1].x, front[i + 1].y, front[i + 1].z);
    } 
    fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
      IOR, RFR, RFL, DIF, AMB, 
      back[0].x, back[0].y, back[0].z,
      back[number_pieces - 1].x, back[number_pieces - 1].y, back[number_pieces - 1].z,
      front[0].x, front[0].y, front[0].z);
    fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
      IOR, RFR, RFL, DIF, AMB, 
      back[number_pieces - 1].x, back[number_pieces - 1].y, back[number_pieces - 1].z,
      front[number_pieces - 1].x, front[number_pieces - 1].y, front[number_pieces - 1].z,
      front[0].x, front[0].y, front[0].z);

} /* end of print_rectangle */

void print_sphere(center_x, center_y, center_z, radius)
float center_x, center_y, center_z, radius;
{
  fprintf(output_file, "S%7.3f %7.3f %7.3f %7.3f %3.1f %3.1f %3.1f %3.1f %3.1f\n",
    center_x, center_y, center_z, radius, 
    IOR, RFR, RFL, DIF, AMB);
} /* end of print_sphere */

void build_main_strut(bstart_x, bstart_y, bstart_z, radius, fbottom_x,
                      fbottom_y, fbottom_z)
float bstart_x, bstart_y, bstart_z, radius, fbottom_x, fbottom_y, fbottom_z;
{
float b_width, t_width, depth, fstart_x, fstart_y, fstart_z, 
      bbottom_x, bbottom_y, bbottom_z, fback_x, fback_y, fback_z,
      bback_x, bback_y, bback_z,
      fback_bottom_x, fback_bottom_y, fback_bottom_z, 
      bback_bottom_x, bback_bottom_y, bback_bottom_z;

  fprintf(output_file, "\*_printing_main_strut_\n");
  b_width = radius * 0.4375;
  t_width = radius * 0.50;
  depth   = radius * 0.0625;
  fstart_x = bstart_x - t_width;
  fstart_y = bstart_y;
  fbottom_z = fstart_z = bstart_z -= depth / 2.0;
  bbottom_x = fbottom_x + b_width;
  bbottom_y = fbottom_y;
  bbottom_z = bstart_z;
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    fstart_x, fstart_y, fstart_z,
    bstart_x, bstart_y, bstart_z,
    fbottom_x, fbottom_y, fbottom_z);
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    bstart_x, bstart_y, bstart_z,
    bbottom_x, bbottom_y, bbottom_z,
    fbottom_x, fbottom_y, fbottom_z);
  fback_x = fstart_x;
  fback_y = fstart_y;
  bback_z = fback_z = fstart_z + depth;
  bback_x = bstart_x;
  bback_y = bstart_y;
  fback_bottom_x = fbottom_x;
  fback_bottom_y = fbottom_y;
  fback_bottom_z = fback_z;
  bback_bottom_x = bbottom_x;
  bback_bottom_y = bbottom_y;
  bback_bottom_z = bbottom_z;
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    fback_bottom_x, fback_bottom_y, fback_bottom_z,
    bback_bottom_x, bback_bottom_y, bback_bottom_z,
    fback_x, fback_y, fback_z);  
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    bback_bottom_x, bback_bottom_y, bback_bottom_z,
    bback_x, bback_y, bback_z,
    fback_bottom_x, fback_bottom_y, fback_bottom_z);
  bbottom_x += fbottom_x + b_width;
  bbottom_y = fbottom_y;
  bbottom_z = bstart_z;
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    bstart_x, bstart_y, bstart_z,
    bback_bottom_x, bback_bottom_y, bback_bottom_z,
    bbottom_x, bbottom_y, bbottom_z);
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    bstart_x, bstart_y, bstart_z, 
    bback_x, bback_y, bback_z,
    bback_bottom_x, bback_bottom_y, bback_bottom_z);
  fprintf(output_file, "\*_ending_main_strut\n");
} /* end of build_main_strut */

void build_primary_hull(start_x, start_y, start_z, number_pieces, radius)
float start_x, start_y, start_z, radius;
int number_pieces;
{
struct vector upper_dish[MAX_PIECES], lower_dish[MAX_PIECES], side[MAX_PIECES],
       inner_dish[MAX_PIECES];
float x[MAX_PIECES], y[MAX_PIECES], z[MAX_PIECES], degrees, inner_radius,
      new_radius, temp_y;
int i;
void build_arc(), print_circle(), print_rectangles();

  if (number_pieces > MAX_PIECES)
    number_pieces = MAX_PIECES;
                                     /* build upper protion of disk */
  build_arc(0.0, 360.0, start_x, start_z, radius, x, z, 0, number_pieces);
  for (i = 0; i < number_pieces; i++)
    {
    upper_dish[i].x = x[i];
    upper_dish[i].y = start_y;
    upper_dish[i].z = z[i];
    lower_dish[i].x = x[i];
    lower_dish[i].y = start_y - (radius / 8.0);
    lower_dish[i].z = z[i];
    } /* end of for */

               /* side section triangles */
    fprintf(output_file, "\*_printing_side_rectangles\n");
    print_rectangles(lower_dish, upper_dish, number_pieces);
    fprintf(output_file, "\*_ending_side_rectangles\n");

    inner_radius = radius * 0.625;
    new_radius = radius * 0.1875;
    build_arc(0.0, 360.0, start_x, start_z, inner_radius, x, z, 0, number_pieces);
    for (i = 0; i < number_pieces; i++)
      {
      inner_dish[i].x = x[i];
      inner_dish[i].y = start_y;
      inner_dish[i].z = z[i];
      }
    print_rectangles(inner_dish, upper_dish, number_pieces);

    build_arc(0.0, 360.0, start_x, start_z, new_radius, x, z, 0, number_pieces); 
    for (i = 0; i < number_pieces; i++)
      {
      upper_dish[i].x = x[i];
      upper_dish[i].y = start_y + (radius / 8.0);
      upper_dish[i].z = z[i];
      }
    print_rectangles(inner_dish, upper_dish, number_pieces);

                /* upper section of hull */
    fprintf(output_file, "\*_upper_section\n");
    print_circle(start_x, upper_dish[0].y, start_z, 
                 upper_dish, number_pieces, UP);
               /* lower section */
    temp_y = start_y - (radius / 8.0);
    for (i = 0; i < number_pieces; i++)
      inner_dish[i].y = temp_y;
    print_rectangles(inner_dish, lower_dish, number_pieces);

    temp_y -= radius / 8.0;
    for (i = 0; i < number_pieces; i++)
      {
      lower_dish[i].x = x[i];
      lower_dish[i].y = temp_y;
      lower_dish[i].z = z[i];
      }
    print_rectangles(lower_dish, inner_dish, number_pieces);

    fprintf(output_file, "\*_lower_section\n");
    print_circle(start_x, temp_y, start_z, lower_dish, number_pieces, DOWN);
    print_sphere(start_x, start_y + radius / 14.0, start_z, radius * 0.125);
    print_sphere(start_x, temp_y + radius / 14.0, start_z, radius * 0.125);
}

void build_propulsion_units(start_x, start_y, start_z, number_pieces, radius)
float start_x, start_y, start_z, radius;
int number_pieces;
{
float x1, y1, z1, x2, eng_rad, x[MAX_PIECES], y[MAX_PIECES], z[MAX_PIECES];
struct vector front[MAX_PIECES], back[MAX_PIECES];
void build_arc(), print_rectangles(), print_sphere();
int i;

  x1 = start_x + radius * 1.21875;
  y1 = start_y + radius * 0.1875;
  z1 = start_z + radius * 0.75;
  x2 = x1 + (radius * 2.125);
  eng_rad = radius * 0.125;
  build_arc(0.0, 360.0, z1, y1, eng_rad, z, y, 0, number_pieces);
  for (i = 0; i < number_pieces; i++)
    {
    front[i].x = x1;
    back[i].x = x2;
    front[i].y = back[i].y = y[i];
    front[i].z = back[i].z = z[i];
    }
  print_rectangles(front, back, number_pieces);
  print_sphere(x1, y1, z1, eng_rad);
}  /* build_propulsion_units */

void print_strut(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, width)
float x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, width;
{
float x5, y5, z5, x6, y6, z6, x7, y7, z7, x8, y8, z8;

  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    x1, y1, z1, x3, y3, z3, x4, y4, z4);
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    x1, y1, z1, x4, y4, z4, x2, y2, z2);
      /* bottom of strut */
  x5 = x1; y5 = y1; z5 = z1 + width * 0.25;
  x6 = x2; y6 = y2; z6 = z2 + width * 0.25;
  x7 = x3; y7 = y3; z7 = z3 + width * 0.25;
  x8 = x4; y8 = y4; z8 = z4 + width * 0.25;
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    x5, y5, z5, x8, y8, z8, x7, y7, z7);
 
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    x5, y5, z5, x6, y6, z6, x8, y8, z8);
        /* front side */
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    x1, y1, z1, x3, y3, z3, x7, y7, z7);
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    x1, y1, z1, x7, y7, z7, x5, y5, z5);

        /* back side */
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    x2, y2, z2, x4, y4, z4, x8, y8, z8);
  fprintf(output_file, "F%3.1f %3.1f %3.1f %3.1f %3.1f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
    IOR, RFR, RFL, DIF, AMB, 
    x2, y2, z2, x8, y8, z8, x6, y6, z6);
} /* end of print_strut */

void build_eng_struts(port_x, port_y, port_z, radius, starboard_x,
        starboard_y, starboard_z, start_x, start_y, start_z)
float port_x, port_y, port_z, radius, starboard_x,
        starboard_y, starboard_z, start_x, start_y, start_z;
{
float x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4, width, depth;
void print_strut();

  printf("in build_eng_strut\n");
  depth = radius * 0.0625;
  width = radius * 0.15625;
  x4 = x2 = port_x - radius * 0.05;
  x3 = x1 = x2 - width;
  y2 = y1 = port_y;
  z2 = z1 = port_z;
  y3 = y4 = start_y + radius * 0.1875;
  z3 = z4 = start_z - radius * 0.75;
  fprintf(output_file, "\*_engine_strut\n");
  print_strut(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, width);
  fprintf(output_file, "\*_end_engine_strut\n");
  x4 = x2 = starboard_x - radius * 0.05;
  x3 = x1 = x2 - width;
  y2 = y1 = starboard_y;
  x2 = z1 = starboard_z;
  z3 = z4 = start_z + radius * 0.75;
  print_strut(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, width);
} /* build_eng_struts */

void build_secondary_hull(start_x, start_y, start_z, number_pieces, radius)
float start_x, start_y, start_z, radius;
int number_pieces;
{
float x1, y1, z1, x2, x[MAX_PIECES], y[MAX_PIECES], z[MAX_PIECES];
struct vector front[MAX_PIECES], back[MAX_PIECES];
int i, index;
void build_arc(), print_rectangles(), build_main_strut(), build_eng_struts();

  x1 = start_x + radius * 0.75;
  y1 = start_y - (radius / 8.0) - (radius * 0.375);
  z1 = start_z;
  build_arc(0.0, 360.0, y1, z1, (radius * 0.21875), y, z, 0, number_pieces);
  for (i = 0; i < number_pieces; i++)
    {
    front[i].x = x1;
    front[i].y = y[i];
    front[i].z = z[i];
    }
  x2 = x1 + (radius * 1.125);
  build_arc(0.0, 360.0, y1, z1, (radius * 0.15625), y, z, 0, number_pieces);
  for (i = 0; i < number_pieces; i++)
    {
    back[i].x = x2;
    back[i].y = y[i];
    back[i].z = z[i];
    }
  print_rectangles(back, front, number_pieces);
  build_main_strut(start_x + radius, 
                   (start_y - (radius / 8.0)),
                   start_z, radius, x1, y1 + radius * 0.11875, z1);
  printf("build_eng_struts\n");
  index = (int) (number_pieces / (int) (number_pieces / 3.0));
  printf("index = %d\n", index);
  build_eng_struts(x2, y[index], 
                   z[index],
                   radius, x2,
                   y[(number_pieces - index)],
                   z[(number_pieces - index)], 
                   start_x, start_y, start_z);
  printf("finished build_eng_strut\n");
}  /* end of build_secondary_hull */

build_deflector(start_x, start_y, start_z, number_pieces, radius)
float start_x, start_y, start_z, radius;
int number_pieces;
{

}

void stars(number, sx, sy, sz)
int number;
float sx, sy, sz;

{
  double x, y, z;
  int i, rnum;
  int rand();
  void print_star();

  srand(100);
  for (i = 0; i < number; i++)
    {
    x = (double) rand(); 
    while (x > 1000.0)
      x /= 10.0;
    y = (double) rand();
    while (y > 1000.0)
      y /= 10.0;
    z = (double) rand() / 100.0;
    while (z > 300.0)
      z /= 10.0;
    z += 700.0;
    print_star(x + sx, y + sy, z + sz, 2.0);
    }  /* end of for */
} /* end of stars */

void print_star(center_x, center_y, center_z, radius)
double center_x, center_y, center_z, radius;
{
  float amb;

  amb = 0.9;
  fprintf(output_file, "S%7.3f %7.3f %7.3f %7.3f %3.1f %3.1f %3.1f %3.1f %3.1f\n",
    center_x, center_y, center_z, radius, 
    IOR, RFR, RFL, DIF, amb);
} /* end of print_star */
