/* preasap.c   a simple preprocesssor for generating linked straigh
wires for the Antenna Analysis Program:  ASAP

by Ray L. Cross
Copyright 1998 All rights reserved.
May by redistributed without limit between private individuals without
prior permission as long as the program remains intact and is not sold.

**** Example Input to preasap follows -- explanation follows the example file **
1.0
2

  4 0

	  0 0 0
	  0 0 10
	  0 10 10
	  10 10 10

  3 0

	  0 0 0
	  0 0 10
	  0 10 10

-2 0
  10 0 0

  0 0

************** End of Example Input file *******

The same file will be repeated, this time with explanations.
The test case file are the numbers on the left; a brief explanation is on
the right.

Numbers are not required to be formated as shown.  Commas should not be
used to separate fields.   As many carriage returns as you like may separate
individual numbers.

1.0          (the maximum length a final segment is allowed to have (meters))
2            (point/segment number to start connection list)

  4 0    (number of                        (min points generated)
		  decription points                     per input segment
			in next wire)

	  0 0 0              (x1) (y1) (z1)
	  0 0 10             (x2) (y2) (z2)
	  0 10 10            (x3) (y3) (z3)
	  10 10 10           (x4) (y4) (z4)

  3 0      (number of                   (min points generated)
			 decription points              ( per input segment  )
				in next wire)

	  0 0 0             (x1) (y1) (z1)
	  0 0 10            (x2) (y2) (z2)
	  0 10 10           (x3) (y3) (z3)

If the number of description points (numdes) is negative, it is interpreted
to mean that the previous wire is to be duplicated -numdes times. In the
negative numdes case minsegs is a dummy value which is ignored and only one
x,y,z coordinate is read which is the relative offset for each duplication.

-2 0      (previous wire to be duplicated 2 times)
  10 0 0  (each duplication will be offset from the last by 10 in the
		x direction)

  0 0         (no more wires)


********
		 */

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


float maxlength ;     /* global for the maximum length of a generated
			 segment */

/* */
int floatoutf();
#define floatout(a) floatoutf(a,0)     /* macros to handle the two modes */
#define floatoutres() floatoutf(0.0,1) /* of floatoutf() */

#define ARRAYMAX 100







main()
{
 int numdespts, minnumsegs, segnum=1,
 bormake(), wiremake(), writegd() ;

FILE *files[2] ;

/* read the maxlength : length of the largest piece
   and the starting point number */

  scanf("%f%d", &maxlength, &segnum) ;

/* open a set of temporary files */
    files[0] = tmpfile() ;    files[1] = tmpfile();

/* read the number of points to describe a wire and the minimum
   number of points per segment, and the segment descripter number */

 while(   scanf("%d%d", &numdespts, &minnumsegs) , numdespts )
  {
    wiremake(numdespts,minnumsegs,&segnum, files) ;
  }

  writegd(files,0);  /* writeout gxyz */
  writegd(files,1);  /* writeout dnode */


} /* end of main */






int writegd(files,mode)
    FILE *files[] ;
    int  mode ;
/*
  writes out either the gxyz section or the dnode section depending on mode
  */
{
 char temp[90] ;

  if (mode)
   {
    printf("DNODE\n");
   }  else
   {
    printf("GXYZ\n");
   }

   rewind(files[mode]);

   while( !feof(files[mode]) )
    {
     if( fgets(temp,90,files[mode]) != NULL)
     printf("%s", temp) ;
	 }
  printf("XXXX\n");


} /* end of wiregd */











/* wiremake generates the wire data given the point data and the segment number
   data, places the data into temporary files */


int wiremake(numdes,minsegs, segnum, files)
    int numdes, minsegs, *segnum ;
    FILE *files[] ;
/*
   wiremake creates the x y z points from the endpoints read in from
   stdin then prints x,y,z to a temporary file.

   If numdes is negative, it is interpreted to mean that the previous
   wire is to be duplicated -numdes times. In the negative numdes case
   minsegs is a dummy value which is ignored and only one x,y,z coordinate
   is read which is the relative offset for each duplication.

      The return value has no meaning.
*/
{
  int i, segs, loop, genwpoints() ;
  float xo, yo, zo ;
  static float x[ARRAYMAX], y[ARRAYMAX], z[ARRAYMAX] ;
  static int wirenum=1, lastnumdes, lastminsegs ;

/* determine if a repeated moved structure is involved */
  loop = 0 ;

  if (numdes>0 )
   {
    /* not a repeated structure - read in the descriptor points */
      for( i=0 ; i<numdes ; i++)
       {
	scanf("%f%f%f", &(x[i]), &(y[i]), &(z[i])  ) ;
       }
     lastnumdes = numdes; lastminsegs = minsegs; /* save for future */
   } else /* is a repeated structure */
   {
    loop = -numdes ;
    numdes = lastnumdes; minsegs = lastminsegs;
    scanf("%f%f%f", &xo, &yo, &zo ) ; /* read offset */
   }

 do
  {
   if(loop)
    {                          /* add offset */
     for( i=0 ; i<numdes ; i++)
       {
	x[i] += xo; y[i] += yo; z[i] += zo;
       }
    }

  segs = genwpoints(numdes,x,y,z,minsegs,wirenum, *segnum, files) ;


	 fprintf(files[1],"  " ) ; /*extra space to make easy to find start of wire*/
                              /* in the connection list  */


  for(i=0 , (*segnum)++ ; i<segs-1 ; i++, (*segnum)++ )
   {
	 fprintf(files[1],"%d %d  / wire: %d\n", (*segnum)-1, *segnum, wirenum ) ;
	}


	wirenum++ ;


  }while(--loop, loop>0 ) ;

}/* end of wiremake */








/* macro for distance */

#define distance(x,y,z) (sqrt((x) * (x) + (y) * (y) + (z) * (z)))









int genwpoints(numofpoints, x, y, z,   minsegs, wire, segment, files)

    int numofpoints, minsegs, wire, segment ;
    float x[], y[], z[] ;
    FILE *files[] ;

    /* global variable maxlength is also used */
/* genwpoints takes the segment end points stored in x y and z and
   generated the intermediate points.   The total number of points
   generated is returned.  Whether or not a particular x y or z value
   is printed depends on mode. */
{

  int i,k,total,segs ;


/* print the first point */
 fprintf(files[0],"%G  %G  %G\t  / \tw%d s%d \n", x[0],y[0],z[0],
						  wire, segment++) ;

 total = 1 ;

 for(i=1 ; i < numofpoints ; i++ )
  {
  /* calculate the number of segments based on length or the minimum number
     of segments allowed */

   segs = 1 + (int)(distance( (x[i]-x[i-1]), (y[i]-y[i-1]), (z[i]-z[i-1]) )
			   / maxlength ) ;

   segs = (segs>minsegs ? segs:minsegs) ;

   if( segs%2 )
     segs++ ;       /* make segs an even number */

   total += segs ;

   /* do the intermediate points */
  for(k=1 ; k<segs ; k++ )
   {
    fprintf(files[0],"%G  %G  %G\t  / \tw%d s%d \n",
	     (k * x[i]/segs + x[i-1] * (1.0 - (float)k/segs) ),
	     (k * y[i]/segs + y[i-1] * (1.0 - (float)k/segs) ),
	     (k * z[i]/segs + z[i-1] * (1.0 - (float)k/segs) ),
	     wire, segment++
	   ) ;
   }

   /*  in order to prevent roundoff errors (important when matching
       wire boundaries) print next point from the matrix (no calc above) */
  fprintf(files[0],"%G  %G  %G\t  / \tw%d s%d \n",  x[i], y[i], z[i],
						    wire, segment++ ) ;

  } /* for(i) */

return total ;
}

