/*
 Program : Coil
 Purpose : Create coil objects for PoV Ray v1.0 raytracer
 Created : 7/25/92
 By      : Bill Kirby CIS [70711,2407]
 File    : Coil.c
 Compiler: Borland C++ v3.1
 Model   : Small
 Comments: Used to create twisted coil object made with spheres
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#ifndef PI
#define PI 3.1415926535897932384626
#endif

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

void show_title(void);
void get_inputs(void);
void write_header(char *filename, char *union_name);
void write_piece(double xpos, double ypos, double zpos, double radius);
void write_end(void);
void err_exit(char *message);

FILE *outfile;
char filename[80],union_name[80],buff[256];
double x1,y1,x2,y2,z2,xpos,ypos,zpos,Rad1,rad2,radius;
double angle1,angle2,k;
long i,j,Ntwist,Ntube,steps;
double xmax = -1e300, xmin = 1e300, ymax = -1e300, ymin = 1e300, zmax = -1e300, zmin = 1e300;

main(argc,argv)
int argc;  char *argv[];
{

    show_title();

/* Get coil values from user */
    get_inputs();

/* Open file for output and write header */
    printf("\n\nCreating data file %s\n",filename);
    if ((outfile = fopen(filename,"w")) == NULL)
     err_exit("Opening file.");

    write_header(filename,union_name);

/* Compute twisted coil object */

    for(i=0;i<steps;++i){
      angle1 = 2 * PI * Ntube * (double)i/ (double)steps;
      x1 = cos( angle1 );
      y1 = sin( angle1 );
      angle2 = (double)( Ntwist + 1.0/Ntube) * angle1;
      x2 = cos( angle2 );
      z2 = sin( angle2);
      xpos = k * ((Rad1 * x1) + (rad2 * x2 * x1));
      ypos = k * ((Rad1 * y1) + (rad2 * x2 * y1));
      zpos = k * rad2 * z2;
      xmax = max(xmax,xpos);
      xmin = min(xmin,xpos);
      ymax = max(ymax,ypos);
      ymin = min(ymin,ypos);
      zmax = max(zmax,zpos);
      zmin = min(zmin,zpos);
      write_piece(xpos,ypos,zpos,radius);
    }

/* Write object end and close file */
    write_end();
    fclose(outfile);
    printf("\nFile %s created.\n",filename);
    return(0);
}

void show_title(void)
{
    printf("Coil v2.00\n");
    printf("Creates a PoV-Ray v1.0 raytracer data file of a twisted coil object.\n");
    printf("- W. D. Kirby 7/25/92\n\n");
}

void get_inputs(void)
{
/* Get coil values from user */

    printf("Ouput filename? [coil.inc]: ");
    gets(buff);
    strcpy(filename,buff);

    printf("Union name? [coil]: ");
    gets(buff);
    strcpy(union_name,buff);

    printf("Number of spheres? [100]: ");
    gets(buff);
    steps = atoi(buff);

    printf("Number of spheres in cross-section? [2]: ");
    gets(buff);
    Ntube = atoi(buff);

    printf("Number of twists per revolution? [2]: ");
    gets(buff);
    Ntwist = atoi(buff);

    printf("Major radius? [1.0]: ");
    gets(buff);
    sscanf (buff, "%lf", &Rad1);

    printf("Minor radius? [0.25]: ");
    gets(buff);
    sscanf (buff, "%lf", &rad2);

    printf("Sphere radius? [0.25]: ");
    gets(buff);
    sscanf (buff, "%lf", &radius);

    printf("Overall scale value (k)? [1.0]: ");
    gets(buff);
    sscanf (buff, "%lf", &k);

/* Set up default values */
    if(filename[0]=='\0') strcpy(filename,"coil.inc");
    if(union_name[0]=='\0') strcpy(union_name,"coil");
    if(steps==0) steps = 100;
    if(Ntube==0) Ntube = 2;
    if(Ntwist==0) Ntwist = 2;
    if(Rad1==0.0) Rad1 = 1.0;
    if(rad2==0.0) rad2 = 0.25;
    if(radius==0.0) radius = 0.25;
    if(k==0.0) k = 1.0;
}

void write_header(char *filename,  char *union_name)
{
    fprintf(outfile,"// File : %s  Union Name : %s \n",filename,union_name);
    fprintf(outfile,"// This data file created by COIL.EXE v2.0 for the PoV Ray v1.0 raytracer.\n");
    fprintf(outfile,"\n//Twists=%ld Cross Section=%ld Spheres=%ld Scale=%lf \n\n",Ntwist,Ntube,steps,k);
    fprintf(outfile,"declare %s = object {\n union {\n",union_name);
}

void write_piece(double xpos, double ypos, double zpos,double radius)
{

    fprintf(outfile,"      sphere { <%f %f %f> %f }\n",xpos,ypos,zpos,radius);

}

void write_end(void)
{
    fprintf(outfile," }\n\n");
    xmax = 1.01 * (xmax + radius);
    xmin = 1.01 * (xmin - radius);
    ymax = 1.01 * (ymax + radius);
    ymin = 1.01 * (ymin - radius);
    zmax = 1.01 * (zmax + radius);
    zmin = 1.01 * (zmin - radius);
    fprintf(outfile,"bounded_by {\n");
    fprintf(outfile,"  box { < %f %f %f > < %f %f %f> }\n",xmin,ymin,zmin,xmax,ymax,zmax);
    fprintf(outfile,"}\n");
    fprintf(outfile,"  texture {\n");
    fprintf(outfile,"    ambient 0.3\n");
    fprintf(outfile,"    diffuse 0.7\n");
    fprintf(outfile,"    phong 1.0\n");
    fprintf(outfile,"    phong_size 20.0\n");
    fprintf(outfile,"    color red 1.0 green 0.0 blue 0.0  \n");
    fprintf(outfile,"  }\n\n");
    fprintf(outfile," }\n\n");
}

void err_exit(char *message)
{
    puts("\n\nERROR! \a");
    puts(message);
    puts("- Exiting \n");
    exit(1);
}
