home *** CD-ROM | disk | FTP | other *** search
- /*
- * xvor.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /*
- * XVOR
- *
- * compute Voronoi diagram or Delaunay triangulation
- * for a set of points in the plane
- *
- * on unsorted data uniformly distributed in the unit square, routine
- * voronoi uses about 20n+140\(srn bytes of storage; on sorted data,
- * routine voronoi uses about 160\(srn
- *
- *
- * input:
- * each input line should consist of two real numbers, separated by
- * white space.
- * sorted input (option -s):
- * the input is sorted by y coordinate (the second number in the pair);
- * the first input line should be npoints xmin xmax ymin ymax; this
- * describes the number of points and the range of the points; the
- * information is used to determine internal hash table size; it need
- * not be exact but performance suffers if it is grossly wrong.
- *
- * VORONOI output:
- * there are four output record types.
- * -->s a b indicates that an input point at coordinates a b was seen;
- * -->l a b c indicates a line with equation ax + by = c.
- * -->v a b indicates a vertex at a b.
- * -->e l v1 v2 s1 s2 indicates a Voronoi segment which is a subsegment of
- * line number l with endpoints numbered v1 and v2; if v1 or v2
- * is -1, the line extends to infinity; e bisects the line segment
- * delimited by sites s1 and s2
- *
- * DELAUNAY output:
- * output: each output line is a triple i j k, giving the indices of
- * the three points in a Delaunay triangle; points are
- * numbered starting at 0.
- *
- */
-
- #include "xvor.h"
-
- /* globals */
- extern char *optarg;
- extern int optind, opterr;
-
-
- int VOR = ON; /* default: evaluate Voronoi diagram */
- int TRIANGULATE = OFF;
- int PRE_SORTED = ON; /* default: assume y-sorted data in input file */
- int DBG = OFF;
-
- int WRITE_FLAG = OFF;
-
- FILE *fpIn, *fpOut;
-
- /*
- * scomp()
- * DESCRIPTION:
- * sort sites on y, then x, coord
- * used with qsort!!
- * ARGUMENTS:
- * S1: first sort poiint (Point *)
- * S2: second sort poiint (Point *)
- * RETURN VALUE:
- * 1, 0, -1 depending on x,y position
- */
-
- int
- scomp (S1, S2)
- const void *S1, *S2;
- {
- const struct Point *s1 = S1;
- const struct Point *s2 = S2;
-
- if (s1->y < s2->y)
- return (-1);
- if (s1->y > s2->y)
- return (1);
- if (s1->x < s2->x)
- return (-1);
- if (s1->x > s2->x)
- return (1);
-
- return (0);
- }
-
- /*
- * nextone()
- * DESCRIPTION:
- * return a single in-storage site
- * ARGUMENTS:
- * none
- * RETURN VALUE:
- * next site (struct Site *)
- */
-
- struct Site *
- nextone ()
- {
- struct Site *s;
-
- if (siteidx < nsites) {
- s = &sites[siteidx];
- siteidx += 1;
- return (s);
- }
- else
- return ((struct Site *) NULL);
- }
-
-
- /*
- * freadsites()
- * DESCRIPTION:
- * read all sites, sort, and compute xmin, xmax, ymin, ymax
- * ARGUMENTS:
- * file: pointer to open FILE
- * RETURN VALUE:
- * none
- */
-
- void
- freadsites (file)
- FILE *file;
- {
- int i;
-
- /*
- * skip top line in .vin data file
- */
- fscanf (file, "%d %f %f %f %f", &nsites, &xmin, &xmax, &ymin, &ymax);
-
- /*
- * read data
- */
- nsites = 0;
- sites = (struct Site *) myalloc (4000 * sizeof (struct Site));
- while (fscanf (file, "%f %f", &sites[nsites].coord.x, &sites[nsites].coord.y) != EOF) {
- sites[nsites].sitenbr = nsites;
- sites[nsites].refcnt = 0;
- nsites += 1;
- if (nsites % 4000 == 0)
- sites = (struct Site *) realloc (sites, (nsites + 4000) * sizeof (struct Site));
- }
-
- /*
- * sort data and find extrema
- */
- qsort (sites, nsites, sizeof (struct Site), scomp);
-
- xmin = sites[0].coord.x;
- xmax = sites[0].coord.x;
- for (i = 1; i < nsites; i += 1) {
- if (sites[i].coord.x < xmin)
- xmin = sites[i].coord.x;
- if (sites[i].coord.x > xmax)
- xmax = sites[i].coord.x;
- }
- ymin = sites[0].coord.y;
- ymax = sites[nsites - 1].coord.y;
-
- #ifdef SHOW_DATA
- printf ("\n...data after sorting:\n");
- printf ("...parameters: nsites: %4d", nsites);
- printf ("\n extrema: %f %f %f %f\n", xmin, xmax, ymin, ymax);
-
- for (i = 0; i < nsites; i += 1) {
- printf (" x[%d] = %f y[%d] = %f\n",
- i, (sites + i)->coord.x, i, (sites + i)->coord.y);
- }
- #endif
- }
-
-
- /*
- * readone()
- * DESCRIPTION:
- * read one site
- * ARGUMENTS:
- * none
- * RETURN VALUE:
- * site (struct Site *)
- */
-
- struct Site *
- readone ()
- {
- struct Site *s;
-
- s = (struct Site *) getfree (&sfl);
-
- s->refcnt = 0;
- s->sitenbr = siteidx;
- siteidx += 1;
-
- if (fscanf (fpIn, "%f %f", &(s->coord.x), &(s->coord.y)) == EOF)
- return ((struct Site *) NULL);
-
- #ifdef SHOW_DATA
- printf ("\n...READONE: fetching site: x[%d] = %f y[%d] = %f\n",
- siteidx, s->coord.x, siteidx, s->coord.y);
- #endif
-
- return (s);
- }
-
-
- void
- exit_messg (str, code)
- char *str;
- int code;
- {
- printf ("\n%s", str);
- exit (code);
- }
-
-
-
- /*
- * usage of routine
- */
- void
- usage (char *progname)
- {
- progname = last_bs (progname);
- printf ("USAGE: %s infile outimg [-w file] [-s] [-t] [-g] [-L]\n", progname);
- printf ("\n%s constructs Voronoi diagram or Delaunay triangulation\n", progname);
- printf ("for a set of points in the plane using Fortune's algorithm.\n");
- printf ("[Fortune 1984]\n\n");
- printf ("ARGUMENTS:\n");
- printf (" infile: input filename (.vin) (ASCII)\n");
- printf (" produced by spp or xah; assumes y-sorted\n");
- printf (" site coordinates unless option -s invoked.\n");
- printf (" outimg: output image filename (TIF)\n\n");
- printf ("OPTIONS:\n");
- printf (" -w file : write output to file ( .vdt) as well as stdout\n");
- printf (" -s: y-sort data in input file\n");
- printf (" -t: perform Delaunay triangulation\n");
- printf (" -g: debug mode\n");
- printf (" -L: print Software License for this module\n");
- exit (1);
- }
-
-
- void
- main (int argc, char *argv[])
- {
- struct Site *(*next) (); /* next is declared to be a ptr */
- /* to a function which returns a
- * /* ptr to struct Site */
-
- int ic, is;
- int i_arg;
- char *buf;
-
- Image *imgOut;
-
- static char wbuf[20];
- static char *inp_suffix =
- {".xxx"}; /* default inp file suffix */
- static char *vin_type =
- {".vin"}; /* suffix for .vin inp file */
- static char *vsuffix =
- {".vdt"}; /* suffix for V. outp file name */
- static char *dsuffix =
- {".ddt"}; /* suffix for D. outp file name */
-
- int reset = 1, no_reset = 0;
-
- /*
- * cmd line options
- */
- static char *optstring = "w:stgL";
-
- buf = argv[1];
-
- /*
- * parse command line
- */
- optind = 3;
- opterr = ON; /* give error messages */
-
- if (argc < 3)
- usage (argv[0]);
-
- while ((i_arg = getopt (argc, argv, optstring)) != EOF) {
- switch (i_arg) {
- case 'w':
- printf ("...option %c: ", i_arg);
- strcpy (wbuf, optarg);
- if ((fpOut = fopen (wbuf, "w")) == NULL) {
- printf ("\n...cannot open %s for writing\n",
- wbuf);
- exit (1);
- }
- printf ("write data to file %s\n", wbuf);
- WRITE_FLAG = ON;
- break;
- case 's':
- printf ("...option %c: ", i_arg);
- printf ("perform sort on y-coord. of input\n");
- PRE_SORTED = OFF;
- break;
- case 't':
- printf ("...option %c: perform Delaunay triangulation\n", i_arg);
- VOR = OFF;
- TRIANGULATE = ON;
-
- /* construct new output file name */
- ic = 0;
- while ((*(wbuf + ic) = *(buf + ic)) != '.')
- ic++;
- for (is = 0; is < 4; is++)
- *(wbuf + (ic) + is) = *(dsuffix + is);
- break;
- case 'g':
- printf ("...option %c: debug mode\n", i_arg);
- DBG = ON;
- break;
- case 'L':
- print_sos_lic ();
- exit (0);
- default:
- printf ("...unknown condition encountered\n");
- exit (1);
- break;
- }
- }
-
- printf ("read data from file %s\n", buf);
- /* get size of data set from file */
- if ((fpIn = fopen (buf, "r")) == NULL) {
- printf ("\n...cannot open input file %s\n", buf);
- exit (1);
- }
-
- /* construct output file name */
- ic = 0;
- while ((*(wbuf + ic) = *(buf + ic)) != '.')
- ic++;
- for (is = 0; is < 4; is++)
- *(wbuf + (ic) + is) = *(vsuffix + is);
- /* strip input file suffix */
- for (is = 0; is < 4; is++)
- *(inp_suffix + is) = *(buf + ic + is);
-
- #ifdef PORTING
- printf ("\n...give size of all structures defined in header file:\n");
- printf (" struct Freenode: %d\n", sizeof (struct Freenode));
- printf (" struct Freelist: %d\n", sizeof (struct Freelist));
- printf (" struct Point: %d\n", sizeof (struct Point));
- printf (" struct Site: %d\n", sizeof (struct Site));
- printf (" struct Edge: %d\n", sizeof (struct Edge));
- printf (" struct Halfedge: %d\n", sizeof (struct Halfedge));
- #endif
-
- /*
- * get data from input file
- */
- if (strcmp (inp_suffix, vin_type) == 0) {
- freeinit (&sfl, sizeof (struct Site));
- if (PRE_SORTED == ON) {
- fscanf (fpIn, "%d %f %f %f %f",
- &nsites, &xmin, &xmax, &ymin, &ymax);
-
- next = readone;
- }
- else {
- freadsites (fpIn);
- next = nextone;
- }
-
- printf ("\n...initialize geometry settings...\n");
- siteidx = 0;
- geominit ();
-
- /* allocate default image buffer for image output */
- imgOut = ImageAlloc ((long) (ymin + ymax), (long) (xmin + xmax), BPS);
-
- printf ("\n...initialize plotting...\n");
- plotinit (imgOut);
-
- if (VOR == ON)
- printf ("\n...start voronoi construction...\n");
- else if (TRIANGULATE == ON)
- printf ("\n...start Delaunay triangulation...\n");
- voronoi (next, imgOut, WHITE);
-
- }
- else
- exit_messg ("\n...unknown inp file suffix", 1);
-
-
- if (WRITE_FLAG == ON)
- fclose (fpOut);
- printf ("\n...writing graphics output file %s\n", argv[2]);
- ImageOut (argv[2], imgOut);
-
- fclose (fpIn);
- }
-