#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;
  void build_primary_hull(), build_propulsion_units(), build_secondary_hull();
    
  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);
  output_file = fopen("enterprise.dat", "w");
  printf("building primary hull\n");
  build_primary_hull(start_x, start_y, start_z, number_pieces, radius);
  fprintf(output_file, "\*_finished_building_primary_hull\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 - 2 * radius, 
                         number_pieces, radius);
  fprintf(output_file, "\*_finished_building_propulsion_units\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);
*/
  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, bstart_x,
      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;

  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;
  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);
} /* 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];
float x[MAX_PIECES], y[MAX_PIECES], z[MAX_PIECES], degrees;
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);
    lower_dish[i].z = z[i];
    } /* end of for */
                /* upper section of hull */
    print_circle(start_x, start_y, start_z, upper_dish, number_pieces, UP);
               /* lower section */
    print_circle(start_x, start_y, start_z, lower_dish, number_pieces, DOWN);

               /* side section triangles */
    print_rectangles(lower_dish, upper_dish, number_pieces);
}

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.03125;
/*
  y1 = start_y + radius * 1.125;
*/
  y1 = start_y + radius * 0.525;
  z1 = start_z + radius * 0.9;
  x2 = x1 + (radius * 2.25);
  eng_rad = radius * 0.25;
  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 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;
void build_arc(), print_rectangles(), build_main_strut();

  x1 = start_x + (radius / 3) * 1.75;
/*
  y1 = start_y - (radius / 8) - (radius * 0.375);
*/
  y1 = start_y - (radius / 8) - (radius * 0.675);
  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.59375);
  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 + 2 * radius), 
                   (start_y - (radius / 8)),
                   start_z, radius, x1, y1 + radius * 0.11875, z1);

}  /* 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;
{

}

