#define DEFINE_GLOBALS
#include "defines.h"
#include <aarg.i.h>
double aa_etof();
#define aargc aa_cmd.vcnt
#define aargok if (aa_cmd.error) return;
#define need_sites(x) if(!sites){printf("Can't do x without sites.\n");return;}

BOOLEAN cyon = 0, sites = 0, new_sites;

/*  Maximum number of vertices permitted in  Mouse()  and  File()  */
#define SITE_ALLOC 100000

Random()
{
    int i;

    aargok;
    s_alloc( n_sites = aa_etof(aargv[1]) );
    INITRAND;
    for ( i=0 ; i<n_sites ; i++ )
       { X(i) = RAND;    Y(i) = RAND; }
    new_sites = sites = 1;
    square();
    triangulate();
}

Mouse()
{
	float x,y;
	char *s = "add point";

	aargok;
	aargc = 0; if (!cyon) Graph();
	clear_screen();
	s_alloc(SITE_ALLOC);
	for ( n_sites = 0; n_sites<SITE_ALLOC ; n_sites++ )
	{
	    if (get_cursor(s,"add point","quit", &x, &y)) break;
	    X(n_sites) = (double) x;
	    Y(n_sites) = (double) y;
	    show_vertex(x,y,1);
	    s = 0;
	}
	new_sites = sites = 1;
	square();
	triangulate();
}

File()
{
    FILE *fd;
    char s[127];

    aargok;
    if (NULL == (fd = fopen(aargv[1],"r")))
    {
	printf("cannot open %s\n",aargv[1]);
	return;
    }
    s_alloc(SITE_ALLOC);
    for( n_sites = 0  ;  fgets(s,127,fd) && n_sites<SITE_ALLOC ; n_sites++ )
    {
	if ( 2 != sscanf(s,"%lf%lf",&X(n_sites),&Y(n_sites)) )
	    { printf("Error in file at point number %d\n", n_sites+1 );
              break; }
    }
    new_sites = sites = 1;
    square();
    triangulate();
}

Lincoln()
{
    FILE *fd;

    aargok;
    need_sites(lincoln);
    if (NULL == (fd = fopen(aargv[1],"w")))
    {
	printf("cannot open %s\n",aargv[1]);
	return;
    }
    lincoln(fd);
}

Graph()
{
    float x = 100, y = 100, xx = 500, yy = 500; 
    char *device = 0, *host = 0;

    aargok;
    if (cyon) stop_cheyenne();
    cyon = 1;

    if (aargc > 0)
	device = aargv[1]; 
    if (aargc > 1) 
	host = aargv[2]; 
    if (aargc > 2)
    {
	x = aa_etof(aargv[3]), y = aa_etof(aargv[4]);
	xx = aa_etof(aargv[5]), yy = aa_etof(aargv[6]);
    }
    start_cheyenne(device,host,x,y,xx,yy);
}

Plot()
{
    char c;
    int which_plot = 0;
    aargok;
    need_sites(plot);
    while (c = *aargv[1]++)
	if (c=='v') which_plot |= 1;
	else if (c=='d') which_plot |= 2;
	else if (c=='c') which_plot |= 4;
	else if (c=='s') which_plot |= 8;
	else if (c=='i') which_plot |= 16;
	else printf("Bad character %c to plot\n",c);

    aargc = 0; if (!cyon) Graph();
    if (which_plot&4) colors(4,1); else colors(2,0);
    clear_screen();
    output_voronoi_diagram(which_plot);
    fflush(stdout);
}

Output()
{
    FILE *fd;
    int i;

    aargok;
    need_sites(output);
    fd = fopen(aargv[1],"w");
    for (i = 0 ; i < n_sites ; i++ )
    fprintf(fd,"%f %f\n",X(i),Y(i));
    fclose(fd);
}

Jiggle()
{
    double r = 0.1;
    aargok;
    need_sites(jiggle);
    if (aargc == 1)
	r = aa_etof(aargv[1]);
    jiggle(r);
    fix();
}

square()
{
    /*Set up solid-liquid boundary at [.3,.7]^2 approximately*/
    SITE_PTR s;

    for_sites(s)
	if (X(s)>.3 && X(s)<.7 && Y(s)>.3 && Y(s)<.7)
	    Type(s) = T_SOLID;
	else
	    Type(s) = T_LIQUID;
    end_sites(s)
}

#define MAXW 100
Wulff()
{
    FILE *fd;
    char s[127];

    aargok;
    if (aargc < 1)
    {
	n_wulff = 0;
	return;
    }
    if (NULL == (fd = fopen(aargv[1],"r")))
    {
	printf("cannot open %s\n",aargv[1]);
	return;
    }
    if (!wulff)
	my_alloc(wulff,struct VEC2, MAXW);
    for( n_wulff = 0  ;  fgets(s,127,fd) && n_wulff<SITE_ALLOC ; n_wulff++ )
    {
	if ( 2 != sscanf(s,"%lf%lf",&wulff[n_wulff].x,&wulff[n_wulff].y) )
	    { printf("Error in file at vector number %d\n", n_wulff+1 );
              break; }
    }
    printf("Read in %d Wulff vectors\n",n_wulff);
}

Go()
{
    SITE_PTR s;
    double r = 0.002;
    int n = 1;

    aargok;
    need_sites(go);
    if (aargc >= 1)
	r = aa_etof(aargv[1]);
    if (aargc == 2)
	n = aa_etof(aargv[2]);

    for (;n;--n)
    {
	gradients();
	for_sites(s)
	    X(s) -= Len_grad(s).x*r;
	    Y(s) -= Len_grad(s).y*r;
	end_sites(s)
	fix();
    }
}

fix()
{
    /*aargok;
    need_sites(fix);*/
    if (! fix_delaunay() )
	printf("Can't fix; retriangulating\n"), triangulate();
    else
    {
	delete_all_faces();
	find_vor_corners();
    }
}

Check()
{
    BOOLEAN ok;
    aargok;
    need_sites(check);
    if (ok = check_delaunay())
        printf("Still a valid delaunay triangulation.\n");
    else
	printf("No longer a valid delaunay triangulation.\n");
    /*********  Too slow
    if (ok != full_check_delaunay())
	printf("Full test doesn't agree\n");
    *********/
}

Quit()
{
    aargok;
    if (cyon) stop_cheyenne();
    aa_quit();
}

struct aarg_cmd cmds[] = {
    AA_BEGIN
	AA_COMMENT
	"This program will compute two-dimensional voronoi diagrams.\n\t\
	Sample commands might be 'vor -r 500 -p dv' or 'vor -m -p v'.\n\t\
	Then while still in the program, you could type 'p c' to show\n\t\
	a new plot of the same sites, or 'm -p d' to get new sites."
    AA_NEXT
	Graph, "[-gr[aphics] [%s [%s [%d %d %d %d]]]]",
	"Open graphics device.  First argument is a string indicating\n\t\
	the device to use: either 'ascii', 'mex', 'sunview' etc.\n\t\
	Default depends on the machine type.  The next string is a host\n\t\
	name to display on a different machine.  The optional\n\t\
	numbers give a canvas size in pixels x,y,X,Y.  Ascii graphics\n\t\
	always goes to a file named 'Voronoi.cy'."
    AA_NEXT
	Random, "[-r[andom] %d]",
	"Generate n sites randomly, and triangulate."
    AA_NEXT
	File, "[-f[ile] %s]",
	"Read sites from file and triangulate.\n\t\
	File format is two numbers per line."
    AA_NEXT
	Mouse, "[-m[ouse]]",
	"Get sites from mouse clicks, and triangulate.  If graphics\n\t\
	has not been initialized, the default graphics is started."
    AA_NEXT
	Plot, "[-p[lot] %s]",
	"Plot any subset of 'vdcsi', meaning Voronoi edges, Delauney edges,\n\t\
	and colored Delauney triangles, sites and interface edges.  If\n\t\
	graphics has not been initialized, the default graphics is started."
    AA_NEXT
	Output, "[-o[utput] %s]",
	"Output sites to a file.  Most useful if sites were generated with\n\t\
	-mouse or -random."
    AA_NEXT
	Lincoln, "[-l[incoln] %s]",
	"Save delaunay triangulation to a lincoln format file."
    AA_NEXT
	Jiggle, "[-j[iggle] [%f]]",
	"Jiggle all sites by a random amount up to value given\n\t\
	(default 0.1)."
    AA_NEXT
	Go, "[-go [%f [%d]]]",
	"Compute derivatives of length, and move sites to reduce it.\n\t\
	First argument gives multiplier for gradient (default .002),\n\t\
	second gives number of times to repeat."
    /*AA_NEXT
	Square, "[-s[quare]]",
	"Set up solid-liquid boundary at [.3,.7]^2 approximately."*/
    /*AA_NEXT
	Fix, "[-fix]",
	"Fix the delaunay triangulation."*/
    AA_NEXT
	Check, "[-c[heck]]",
	"Do a full check on the delaunay triangulation."
    AA_NEXT
	Wulff, "[-w[ulff] [%s]]",
	"Read in wulff vectors from a file.  Switch to using\n\t\
	crystalline energy."
    AA_NEXT
	Quit, "[-q[uit]]",
	"exit program"
    AA_END,
    AA_STDCMD,
    AA_LASTCMD
};

main(argc,argv) 
int argc;
char **argv;
{
    aa_SetBothModes();
    cy_initialize();
    do_aargs(cmds,argc,argv);
}

