/*
 *	pleat -
 *	    laser score and cut a folded pleated surface
 *
 *	To compile: 
		cc pleat.c -o pleat -lgl -lm
	To run
		pleat pleat.dxf
 *
 *			Paul Haeberli - 1996
 */
#include "stdio.h"
#include "math.h"
#include "gl.h"
#include "device.h"

#define SCORE	0
#define CUT1	1
#define CUT2	2

#define PAGEXSIZE	(36.0)
#define PAGEYSIZE	(24.0)

FILE *outf;
float geom[2000][2];
int nvert;
float xmin, xmax, ymin, ymax;

main(argc,argv)
int argc;
char **argv;
{
    int xsize, ysize;

    if(argc<2) {
	fprintf(stderr,"usage: pleat pleat.dxf\n");
	exit(1);
    }
    xsize = 900;
    ysize = (PAGEYSIZE*xsize)/PAGEXSIZE;
    prefsize(xsize,ysize);
    winopen("laser");
    RGBmode();
    gconfig();
    ortho2(-0.1,PAGEXSIZE+0.1,-0.1,PAGEYSIZE);
    scale(1.0,1.0,1.0);

    dxf_begin(argv[1]);
    project_pleat(); 
    dxf_end();
    sleep(5); /* can be deleted */
}

#define XSPACE		(1.4)
#define YSIZE		(8.5)
#define NSECTIONS	(24)

project_pleat()
{
    putzigzag(XSPACE,YSIZE,NSECTIONS);
    putdiag(XSPACE,      1.9,      3.4,NSECTIONS);
    putdiag(XSPACE,      2.5,      4.0,NSECTIONS);
    putdiag(XSPACE,YSIZE-2.5,YSIZE-4.0,NSECTIONS);
    putdiag(XSPACE,YSIZE-1.9,YSIZE-3.4,NSECTIONS);
    cutrect(0.0,XSPACE*NSECTIONS,0.0,YSIZE);
}

putzigzag(xspace,ysize,n)
float xspace, ysize;
int n;
{
    int i;
    
    for(i=1; i<n; i++) {
	geom[0][0] = i*xspace;
	geom[0][1] = 0.0;
	geom[1][0] = i*xspace;
	geom[1][1] = ysize;
	putpoly(geom,2,SCORE);
    }
}

putdiag(xspace,y1,y2,n)
float xspace, y1, y2;
int n;
{
    int i;
    
    for(i=0; i<=n; i++) {
	if(i&1) {
	    geom[i][0] = i*xspace;
	    geom[i][1] = y2;
	} else {
	    geom[i][0] = i*xspace;
	    geom[i][1] = y1;
	}
    }
    putpoly(geom,n+1,SCORE);
}

cutrect(x1,x2,y1,y2)
float x1, x2, y1, y2;
{
    geom[0][0] = x1;
    geom[0][1] = y1;
    geom[1][0] = x2;
    geom[1][1] = y1;
    geom[2][0] = x2;
    geom[2][1] = y2;
    geom[3][0] = x1;
    geom[3][1] = y2;
    geom[4][0] = x1;
    geom[4][1] = y1;
    putpoly(geom,5,CUT2);
}

dxf_begin(ofname)
char *ofname;
{
    outf = fopen(ofname,"w");
    if(!outf) {
	fprintf(stderr,"dxf: can't open output file %s\n",ofname);
	exit(1);
    }
    fprintf(outf,"  0\n");
    fprintf(outf,"SECTION\n");
    fprintf(outf,"  2\n");
    fprintf(outf,"ENTITIES\n");
    cpack(0xffffff);
    clear();
    ymin = xmin =  10000.0;
    ymax = xmax = -10000.0;
}

tallydomain(x,y)
float x, y;
{
    if(xmin>x) xmin = x;
    if(xmax<x) xmax = x;
    if(ymin>y) ymin = y;
    if(ymax<y) ymax = y;
}

dxf_end()
{
    fprintf(stderr,"Domain is x: %f %f y: %f %f\n",xmin,xmax,ymin,ymax);
    fprintf(outf,"  0\n");
    fprintf(outf,"ENDSEC\n");
    fprintf(outf,"  0\n");
    fprintf(outf,"EOF\n");
    fclose(outf);
    sleep(10);
}

printlayer(layer)
int layer;
{
    switch(layer) {
	case SCORE:
	    fprintf(outf,"  8\n");
	    fprintf(outf,"1S\n");
	    break;
	case CUT1:
	    fprintf(outf,"  8\n");
	    fprintf(outf,"2C\n");
	    break;
	case CUT2:
	    fprintf(outf,"  8\n");
	    fprintf(outf,"3C\n");
	    break;
	default:
	    fprintf(stderr,"dfx: bad layer id\n");
	    break;
    }
}

setcolor(layer)
int layer;
{
    switch(layer) {
	case SCORE:
	    cpack(0x808080);
	    break;
	case CUT1:
	    cpack(0xffc0c0);
	    break;
	case CUT2:
	    cpack(0xff0000);
	    break;
	default:
	    fprintf(stderr,"dfx: bad layer id\n");
	    break;
    }
}

putpoly(coords,n,layer)
float coords[][2];
int n, layer;
{
    int i, closed;

    if(n<2) {
	fprintf(stderr,"error: poly with less than 2 verts!\n");
	return;
    }
    if( n>2 && (coords[0][0] == coords[n-1][0]) &&
               (coords[0][1] == coords[n-1][1]) ) {
	closed = 1;
	n--;
    } else
	closed = 0;

    fprintf(outf,"  0\n");
    fprintf(outf,"POLYLINE\n");
    printlayer(layer);

    fprintf(outf," 66\n");
    fprintf(outf,"     1\n");
    fprintf(outf," 10\n");
    fprintf(outf,"0.0\n");
    fprintf(outf," 20\n");
    fprintf(outf,"0.0\n");

    fprintf(outf," 70\n");
    if(closed)
	fprintf(outf,"     1\n");
    else
	fprintf(outf,"     0\n");

    for(i=0; i<n; i++) {
	fprintf(outf,"  0\n");
	fprintf(outf,"VERTEX\n");
	printlayer(layer);
	fprintf(outf," 10\n");
	tallydomain(coords[i][0],coords[i][1]);
	printcoord(outf,coords[i][0]);
	fprintf(outf," 20\n");
	printcoord(outf,coords[i][1]);
    }
    fprintf(outf,"  0\n");
    fprintf(outf,"SEQEND\n");
    printlayer(layer);

/* display the polygon */
    setcolor(layer);
    pushmatrix();
    translate(0.0,0.0,0.0);
    bgnline();
    for(i=0; i<n; i++)
	v2f(coords[i]);
    if(closed)
	v2f(coords[0]);
    endline();
    popmatrix();

    sginap(10); /* just to see drawing order */
}

printcoord(f,val)
FILE *f;
float val;
{
    char str[1024];
    char *eptr;

    sprintf(str,"%3.6f",val);
    eptr = str+strlen(str)-1;
    while(eptr>(str+1)) {
	if((eptr[0] == '0') && (eptr[-1] != '.')) {
	    eptr[0] = 0;
	    eptr--;
	} else
	    break;
    }
    fprintf(f,"%s\n",str);
}

