home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume41 / vregion / part01 < prev    next >
Encoding:
Text File  |  1993-12-19  |  64.4 KB  |  2,569 lines

  1. Newsgroups: comp.sources.misc
  2. From: seth@tachyon.princeton.edu (Seth Teller)
  3. Subject: v41i030:  vregion - 2D C-callable voronoi, delaunay, convex hull, Part01/01
  4. Message-ID: <1993Dec14.041433.2602@sparky.sterling.com>
  5. X-Md4-Signature: ecb218dc53e655cf4d8fd3fd7a396566
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Princeton University
  8. Date: Tue, 14 Dec 1993 04:14:33 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: seth@tachyon.princeton.edu (Seth Teller)
  12. Posting-number: Volume 41, Issue 30
  13. Archive-name: vregion/part01
  14. Environment: UNIX
  15.  
  16. This code computes the voronoi diagram, delaunay triangulation,
  17. and convex hull of a two-dimensional point set.  It's based
  18. on Steve Fortune's algorithm, and partially on his implementation.
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then feed it
  22. # into a shell via "sh file" or similar.  To overwrite existing files,
  23. # type "sh file -c".
  24. # Contents:  Makefile edgelist.c heap.c main.c memory.c vordefs.h
  25. #   voronoi.c voronoi.h vortest.c vregion.c vregion.man vrgeometry.c
  26. # Wrapped by kent@sparky on Mon Dec 13 22:10:10 1993
  27. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  28. echo If this archive is complete, you will see the following message:
  29. echo '          "shar: End of archive 1 (of 1)."'
  30. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'Makefile'\"
  32. else
  33.   echo shar: Extracting \"'Makefile'\" \(1068 characters\)
  34.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  35. XNAME=vor
  36. XINCDIRS=-I/usr/include -I${BASE}/src
  37. X
  38. XCFLAGS=-float -g -Wp,-B -prototypes
  39. XOPTCFLAGS=-float -O2 -Wp,-B -prototypes -DNDEBUG -DGL -DINLINE $(INCDIRS)
  40. X
  41. X# on a non-sgi
  42. XCFLAGS=
  43. XOPTCFLAGS=-O2
  44. X
  45. XAPPCFILES=edgelist.c vrgeometry.c heap.c main.c memory.c voronoi.c vregion.c
  46. XLIBCFILES=edgelist.c vrgeometry.c heap.c memory.c voronoi.c vregion.c
  47. XLIBOBJS=${LIBCFILES:.c=.o}
  48. X
  49. X# libraries this lib depends on
  50. XLIBDEPS=-lm
  51. X
  52. Xdefault:
  53. X    make $(NAME)
  54. X    make ascii_test
  55. X    make grfix_test
  56. X
  57. X$(NAME):    $(LIBOBJS)
  58. X    /bin/rm -f ${BASE}/lib/lib$(NAME).a
  59. X    ar crlvs ${BASE}/lib/lib$(NAME).a $(LIBOBJS)
  60. X
  61. Xascii_test:    $(NAME)test.o
  62. X    cc -o $(NAME)test $(NAME)test.o -L${BASE}/lib -l$(NAME) $(LIBDEPS)
  63. X
  64. Xgrfix_test:    main.o
  65. X    cc -o main main.o -L${BASE}/lib -l$(NAME) -lm -lgl_s
  66. X
  67. Xshar:
  68. X    shar $(LIBCFILES) *.h main.c vortest.c vregion.man Makefile > $(NAME).shar
  69. X
  70. Xopt:
  71. X    make $(LIBOBJS) "CFLAGS=$(OPTCFLAGS)"
  72. X    /bin/rm -f ${BASE}/lib/lib$(NAME).a
  73. X    ar crlvts ${BASE}/lib/lib$(NAME).a $(LIBOBJS)
  74. X
  75. Xclean:
  76. X    rm -f core *.o *.BAK *.CKP *.nroff
  77. X
  78. Xclobber: clean
  79. X    rm -f ${BASE}/lib/lib$(NAME).a main vortest
  80. X    
  81. END_OF_FILE
  82.   if test 1068 -ne `wc -c <'Makefile'`; then
  83.     echo shar: \"'Makefile'\" unpacked with wrong size!
  84.   fi
  85.   # end of 'Makefile'
  86. fi
  87. if test -f 'edgelist.c' -a "${1}" != "-c" ; then 
  88.   echo shar: Will not clobber existing file \"'edgelist.c'\"
  89. else
  90.   echo shar: Extracting \"'edgelist.c'\" \(3566 characters\)
  91.   sed "s/^X//" >'edgelist.c' <<'END_OF_FILE'
  92. X#include "vordefs.h"
  93. X
  94. Xint ntry, totalsearch;
  95. X
  96. XELinitialize()
  97. X{
  98. X    int i;
  99. X
  100. X    freeinit(&hfl, sizeof **ELhash);
  101. X    ELhashsize = 2 * sqrt_nsites;
  102. X    ELhash = (struct Halfedge **) myalloc ( sizeof (*ELhash) * ELhashsize);
  103. X    for(i=0; i<ELhashsize; i +=1) 
  104. X    ELhash[i] = (struct Halfedge *)NULL;
  105. X    ELleftend = HEcreate( (struct Edge *)NULL, 0);
  106. X    ELrightend = HEcreate( (struct Edge *)NULL, 0);
  107. X    ELleftend->ELleft = (struct Halfedge *)NULL;
  108. X    ELleftend->ELright = ELrightend;
  109. X    ELrightend->ELleft = ELleftend;
  110. X    ELrightend->ELright = (struct Halfedge *)NULL;
  111. X    ELhash[0] = ELleftend;
  112. X    ELhash[ELhashsize-1] = ELrightend;
  113. X}
  114. X
  115. Xstruct Halfedge *HEcreate(e, pm)
  116. Xstruct Edge *e;
  117. Xint pm;
  118. X{
  119. X    struct Halfedge *answer;
  120. X
  121. X    answer = (struct Halfedge *) getfree(&hfl);
  122. X    answer->ELedge = e;
  123. X    answer->ELpm = pm;
  124. X    answer->PQnext = (struct Halfedge *) NULL;
  125. X    answer->vertex = (struct Site *) NULL;
  126. X    answer->ELrefcnt = 0;
  127. X    return(answer);
  128. X}
  129. X
  130. XELinsert(lb, new)
  131. Xstruct    Halfedge *lb, *new;
  132. X{
  133. X    new->ELleft = lb;
  134. X    new->ELright = lb->ELright;
  135. X    (lb->ELright)->ELleft = new;
  136. X    lb->ELright = new;
  137. X}
  138. X
  139. X/* Get entry from hash table, pruning any deleted nodes */
  140. Xstruct Halfedge *ELgethash(b)
  141. Xint b;
  142. X{
  143. X    struct Halfedge *he;
  144. X
  145. X    if(b<0 || b>=ELhashsize) 
  146. X    return((struct Halfedge *) NULL);
  147. X    he = ELhash[b]; 
  148. X    if (he == (struct Halfedge *)NULL || he->ELedge!=(struct Edge *)DELETED) 
  149. X    return (he);
  150. X
  151. X/* Hash table points to deleted half edge.  Patch as necessary. */
  152. X    ELhash[b] = (struct Halfedge *) NULL;
  153. X    if ((he->ELrefcnt -= 1) == 0) makefree(he, &hfl);
  154. X    return ((struct Halfedge *) NULL);
  155. X}    
  156. X
  157. Xstruct Halfedge *ELleftbnd(p)
  158. Xstruct Point *p;
  159. X{
  160. X    int i, bucket;
  161. X    struct Halfedge *he;
  162. X
  163. X/* Use hash table to get close to desired halfedge */
  164. X    bucket = (p->x - vxmin)/vdeltax * ELhashsize;
  165. X    if(bucket<0) 
  166. X    bucket =0;
  167. X    if(bucket>=ELhashsize) 
  168. X    bucket = ELhashsize - 1;
  169. X    he = ELgethash(bucket);
  170. X    if(he == (struct Halfedge *) NULL) {   
  171. X    for(i=1; 1 ; i += 1) {    
  172. X        if ((he=ELgethash(bucket-i)) != (struct Halfedge *) NULL) 
  173. X        break;
  174. X        if ((he=ELgethash(bucket+i)) != (struct Halfedge *) NULL) 
  175. X        break;
  176. X    }
  177. X    totalsearch += i;
  178. X    }
  179. X    ntry += 1;
  180. X
  181. X/* Now search linear list of halfedges for the corect one */
  182. X    if (he==ELleftend  || (he != ELrightend && right_of(he,p))) {
  183. X    do {
  184. X        he = he->ELright;
  185. X    } while (he!=ELrightend && right_of(he,p));
  186. X         he = he->ELleft;
  187. X    } else 
  188. X    do {
  189. X        he = he->ELleft;
  190. X    } while (he!=ELleftend && !right_of(he,p));
  191. X
  192. X/* Update hash table and reference counts */
  193. X    if(bucket > 0 && bucket <ELhashsize-1) {    
  194. X    if(ELhash[bucket] != (struct Halfedge *) NULL) 
  195. X        ELhash[bucket]->ELrefcnt -= 1;
  196. X    ELhash[bucket] = he;
  197. X    ELhash[bucket]->ELrefcnt += 1;
  198. X    }
  199. X    return (he);
  200. X}
  201. X
  202. X/*
  203. X *  This delete routine can't reclaim node, since pointers from hash
  204. X *  table may be present.   
  205. X */
  206. XELdelete(he)
  207. Xstruct Halfedge *he;
  208. X{
  209. X    (he->ELleft)->ELright = he->ELright;
  210. X    (he->ELright)->ELleft = he->ELleft;
  211. X    he->ELedge = (struct Edge *)DELETED;
  212. X}
  213. X
  214. Xstruct Halfedge *ELright(he)
  215. Xstruct Halfedge *he;
  216. X{
  217. X    return (he->ELright);
  218. X}
  219. X
  220. Xstruct Halfedge *ELleft(he)
  221. Xstruct Halfedge *he;
  222. X{
  223. X    return (he->ELleft);
  224. X}
  225. X
  226. Xstruct Site *leftreg(he)
  227. Xstruct Halfedge *he;
  228. X{
  229. X    if(he->ELedge == (struct Edge *)NULL) 
  230. X    return(bottomsite);
  231. X    return( he->ELpm == le ? he->ELedge->reg[le] : he->ELedge->reg[re]);
  232. X}
  233. X
  234. Xstruct Site *rightreg(he)
  235. Xstruct Halfedge *he;
  236. X{
  237. X    if(he->ELedge == (struct Edge *)NULL) 
  238. X    return(bottomsite);
  239. X    return( he->ELpm == le ? he->ELedge->reg[re] : he->ELedge->reg[le]);
  240. X}
  241. END_OF_FILE
  242.   if test 3566 -ne `wc -c <'edgelist.c'`; then
  243.     echo shar: \"'edgelist.c'\" unpacked with wrong size!
  244.   fi
  245.   # end of 'edgelist.c'
  246. fi
  247. if test -f 'heap.c' -a "${1}" != "-c" ; then 
  248.   echo shar: Will not clobber existing file \"'heap.c'\"
  249. else
  250.   echo shar: Extracting \"'heap.c'\" \(1810 characters\)
  251.   sed "s/^X//" >'heap.c' <<'END_OF_FILE'
  252. X#include "vordefs.h"
  253. X
  254. XPQinsert(he, v, offset)
  255. Xstruct Halfedge *he;
  256. Xstruct Site *v;
  257. Xfloat     offset;
  258. X{
  259. X    struct Halfedge *last, *next;
  260. X
  261. X    he->vertex = v;
  262. X    ref(v);
  263. X    he->ystar = v->coord.y + offset;
  264. X    last = &PQhash[PQbucket(he)];
  265. X    while ((next = last->PQnext) != (struct Halfedge *) NULL &&
  266. X      (he->ystar  > next->ystar  ||
  267. X    (he->ystar == next->ystar && v->coord.x > next->vertex->coord.x))) {
  268. X    last = next;
  269. X    }
  270. X    he->PQnext = last->PQnext; 
  271. X    last->PQnext = he;
  272. X    PQcount += 1;
  273. X}
  274. X
  275. XPQdelete(he)
  276. Xstruct Halfedge *he;
  277. X{
  278. X    struct Halfedge *last;
  279. X
  280. X    if(he-> vertex != (struct Site *) NULL) {    
  281. X    last = &PQhash[PQbucket(he)];
  282. X    while (last->PQnext != he) 
  283. X        last = last->PQnext;
  284. X    last->PQnext = he->PQnext;
  285. X    PQcount -= 1;
  286. X    deref(he->vertex);
  287. X    he->vertex = (struct Site *) NULL;
  288. X    }
  289. X}
  290. X
  291. Xint PQbucket(he)
  292. Xstruct Halfedge *he;
  293. X{
  294. X    int bucket;
  295. X
  296. X    bucket = (he->ystar - vymin)/vdeltay * PQhashsize;
  297. X    if (bucket<0) 
  298. X    bucket = 0;
  299. X    if (bucket>=PQhashsize) 
  300. X    bucket = PQhashsize-1 ;
  301. X    if (bucket < PQmin) 
  302. X    PQmin = bucket;
  303. X    return(bucket);
  304. X}
  305. X
  306. Xint PQempty()
  307. X{
  308. X    return(PQcount==0);
  309. X}
  310. X
  311. Xstruct Point PQ_min()
  312. X{
  313. X    struct Point answer;
  314. X
  315. X    while(PQhash[PQmin].PQnext == (struct Halfedge *)NULL) 
  316. X    PQmin += 1;
  317. X    answer.x = PQhash[PQmin].PQnext->vertex->coord.x;
  318. X    answer.y = PQhash[PQmin].PQnext->ystar;
  319. X    return (answer);
  320. X}
  321. X
  322. Xstruct Halfedge *PQextractmin()
  323. X{
  324. X    struct Halfedge *curr;
  325. X
  326. X    curr = PQhash[PQmin].PQnext;
  327. X    PQhash[PQmin].PQnext = curr->PQnext;
  328. X    PQcount -= 1;
  329. X    return(curr);
  330. X}
  331. X
  332. XPQinitialize()
  333. X{
  334. X    int i; struct Point *s;
  335. X
  336. X    PQcount = 0;
  337. X    PQmin = 0;
  338. X    PQhashsize = 4 * sqrt_nsites;
  339. X    PQhash = (struct Halfedge *) myalloc(PQhashsize * sizeof (struct Halfedge));
  340. X    for(i=0; i<PQhashsize; i+=1) 
  341. X    PQhash[i].PQnext = (struct Halfedge *)NULL;
  342. X}
  343. X
  344. END_OF_FILE
  345.   if test 1810 -ne `wc -c <'heap.c'`; then
  346.     echo shar: \"'heap.c'\" unpacked with wrong size!
  347.   fi
  348.   # end of 'heap.c'
  349. fi
  350. if test -f 'main.c' -a "${1}" != "-c" ; then 
  351.   echo shar: Will not clobber existing file \"'main.c'\"
  352. else
  353.   echo shar: Extracting \"'main.c'\" \(4703 characters\)
  354.   sed "s/^X//" >'main.c' <<'END_OF_FILE'
  355. X/*
  356. X
  357. Xthis is a graphical version of main.c.
  358. X
  359. Xcompile as cc -float -g -prototypes -DGL -c main.c
  360. X
  361. Xlink as cc -o main main.o ~/base/lib/libvor.a -lm -lgl_s
  362. X
  363. X*/
  364. X
  365. X#include "stdio.h"
  366. X#include "voronoi.h"
  367. X#include "gl.h"
  368. X#include <gl/gl.h>
  369. X#include <gl/device.h>
  370. X
  371. X#define E    (0.02)
  372. X
  373. X/*
  374. Xvoid bailout (char *s)
  375. X{
  376. X    exit (0);
  377. X}
  378. X*/
  379. X
  380. X/* example for use of voronoi region package    */
  381. X/*  create data in xy float array        */
  382. X/*  call load_vsites() to create vor diagram    */
  383. X/*  call find_vregion() to query structure    */
  384. X
  385. Xfloat data[][2] = {
  386. X            {-1.0448985, 0.6952569},
  387. X            {-0.2643085,-0.1562872},
  388. X            {-0.3617359,-0.8812830},
  389. X            {-0.9136937,-0.6788232},
  390. X            {-0.9266945, 0.3022859},
  391. X            {-0.3424, 0.6394},
  392. X            {-0.1645, 0.895443},
  393. X            {-0.9345435, 0.4523450},
  394. X
  395. X            /* sentinel entry */
  396. X            { -9999.0, -9999.0 }
  397. X          };
  398. X
  399. Xmain()
  400. X{
  401. Xint n=0, sid, vid, plen;
  402. Xfloat pverts[256][2];
  403. Xint ntris, tid, nchverts;
  404. XTRI *dtris;
  405. XNVERT *chverts;
  406. Xchar nstr[32];
  407. X
  408. X    foreground();
  409. X    /* prefsize(400,400); */
  410. X    winopen("vor");
  411. X    color(15);
  412. X    clear();
  413. X    color(0);
  414. X    ortho2(-2.1,2.1,-2.1,2.1);
  415. X
  416. X    /* count the number of sites in data array (sizeof() should work, but doesn't) */
  417. X    while (data[n][0] != -9999.0 || data[n][1] != -9999.0)
  418. X    n++;
  419. X
  420. X    printf ("found %d vertices in data:\n", n);
  421. X
  422. X    for (sid = 0; sid < n; sid++) {
  423. X    printf ("site %d:\t(%f, %f)\n", sid, data[sid][0], data[sid][1]);
  424. X    color(1);
  425. X    rectf(data[sid][0]-E,data[sid][1]-E,data[sid][0]+E,data[sid][1]+E);
  426. X    }
  427. X
  428. X    printf ("calling load_vsites() with user bbox\n");
  429. X    load_vsites (n, data, -2.0, -2.0, 2.0, 2.0);
  430. X
  431. X    for (sid = 0; sid < n; sid++) {
  432. X    plen = find_vregion (sid, pverts);
  433. X    printf ("region of site %d has length %d\n", sid, plen);
  434. X
  435. X    color(2);
  436. X    bgnclosedline();
  437. X    for (vid = 0; vid < plen; vid++) {
  438. X        printf ("\t%f %f\n", pverts[vid][0], pverts[vid][1]);
  439. X        v2f(pverts[vid]);
  440. X    }
  441. X    endclosedline();
  442. X    }
  443. X
  444. X
  445. X    ntris = find_dtriangles (&dtris);
  446. X    for (tid = 0; tid < ntris; tid++)    {
  447. X    printf ("delaunay triangle %d has vertices %d, %d, %d\n", 
  448. X        tid, dtris[tid].v1->vpid, dtris[tid].v2->vpid, dtris[tid].v3->vpid);
  449. X    printf ("\tcoords (%f, %f)  (%f, %f)  (%f, %f)\n", 
  450. X        dtris[tid].v1->x, dtris[tid].v1->y, dtris[tid].v2->x, dtris[tid].v2->y, dtris[tid].v3->x, dtris[tid].v3->y);
  451. X    
  452. X        color(0);
  453. X        bgnclosedline();
  454. X            v2f((float*)(dtris[tid].v1));    /*pass a 2 element float array to graphics pipe*/
  455. X        v2f((float*)(dtris[tid].v2));
  456. X        v2f((float*)(dtris[tid].v3));
  457. X        endclosedline();
  458. X    }
  459. X
  460. X    nchverts = find_convexhull (&chverts);
  461. X    color(6);
  462. X    bgnclosedline();
  463. X    for (vid = 0; vid < nchverts; vid++)    {
  464. X    printf ("convex hull vertex %d has id %d [bk %d, fw %d]\n", vid, chverts[vid].vpid, chverts[vid].nbr1, chverts[vid].nbr2);
  465. X        v2f(data[chverts[vid].vpid]);
  466. X    }
  467. X    endclosedline();
  468. X
  469. X    color(4);
  470. X    for (vid = 0; vid < nchverts; vid++)    {
  471. X    sprintf (nstr, "%d [%d]", vid, chverts[vid].vpid);
  472. X    cmov2 (data[chverts[vid].vpid][0], data[chverts[vid].vpid][1]);
  473. X    charstr (nstr);
  474. X    }
  475. X
  476. X    printf ("calling load_vsites() with no bbox\n");
  477. X    load_vsites (n, data, 0.0, 0.0, 0.0, 0.0);
  478. X
  479. X    for (sid = 0; sid < n; sid++) {
  480. X    plen = find_vregion (sid, pverts);
  481. X    printf ("region of site %d has length %d\n", sid, plen);
  482. X    for (vid = 0; vid < plen; vid++)
  483. X        printf ("\t%f %f\n", pverts[vid][0], pverts[vid][1]);
  484. X    }
  485. X
  486. X    ntris = find_dtriangles (&dtris);
  487. X    for (tid = 0; tid < ntris; tid++)    {
  488. X    printf ("delaunay triangle %d has vertices %d, %d, %d\n", 
  489. X        tid, dtris[tid].v1->vpid, dtris[tid].v2->vpid, dtris[tid].v3->vpid);
  490. X    printf ("\tcoords (%f, %f)  (%f, %f)  (%f, %f)\n", 
  491. X        dtris[tid].v1->x, dtris[tid].v1->y, dtris[tid].v2->x, dtris[tid].v2->y, dtris[tid].v3->x, dtris[tid].v3->y);
  492. X    }
  493. X
  494. X    nchverts = find_convexhull (&chverts);
  495. X    for (vid = 0; vid < nchverts; vid++)    {
  496. X    printf ("convex hull vertex %d has id %d [bk %d, fw %d]\n", vid, chverts[vid].vpid, chverts[vid].nbr1, chverts[vid].nbr2);
  497. X    }
  498. X
  499. X    {
  500. X    int k, nadjs, (*adjs)[][2];        /* pointer  to nx2 array of ints */
  501. X
  502. X    nadjs = find_dtadjacencies (&adjs);
  503. X
  504. X    if (nadjs > 0)  {
  505. X        color(3);
  506. X
  507. X    for (k = 0; k < nadjs; k++) {    
  508. X        printf ("found adj between tri %d and %d\n", (*adjs)[k][0], (*adjs)[k][1]);
  509. X
  510. X        move2 ((dtris[(*adjs)[k][0]].v1->x + dtris[(*adjs)[k][0]].v2->x + dtris[(*adjs)[k][0]].v3->x) / 3.0, 
  511. X           (dtris[(*adjs)[k][0]].v1->y + dtris[(*adjs)[k][0]].v2->y + dtris[(*adjs)[k][0]].v3->y) / 3.0); 
  512. X        draw2 ((dtris[(*adjs)[k][1]].v1->x + dtris[(*adjs)[k][1]].v2->x + dtris[(*adjs)[k][1]].v3->x) / 3.0, 
  513. X           (dtris[(*adjs)[k][1]].v1->y + dtris[(*adjs)[k][1]].v2->y + dtris[(*adjs)[k][1]].v3->y) / 3.0); 
  514. X        } 
  515. X    }
  516. X
  517. X    }
  518. X
  519. X    while(!getbutton(MOUSE1))
  520. X     sleep(1);
  521. X    
  522. X    exit(0);
  523. X}
  524. X
  525. X
  526. END_OF_FILE
  527.   if test 4703 -ne `wc -c <'main.c'`; then
  528.     echo shar: \"'main.c'\" unpacked with wrong size!
  529.   fi
  530.   # end of 'main.c'
  531. fi
  532. if test -f 'memory.c' -a "${1}" != "-c" ; then 
  533.   echo shar: Will not clobber existing file \"'memory.c'\"
  534. else
  535.   echo shar: Extracting \"'memory.c'\" \(1212 characters\)
  536.   sed "s/^X//" >'memory.c' <<'END_OF_FILE'
  537. X#include <stdio.h>
  538. X#include "vordefs.h"
  539. X
  540. Xfreeinit(fl, size)
  541. Xstruct    Freelist *fl;
  542. Xint    size;
  543. X{
  544. X    fl->head = (struct Freenode *) NULL;
  545. X    fl->nodesize = size;
  546. X}
  547. X
  548. Xchar *getfree(fl)
  549. Xstruct    Freelist *fl;
  550. X{
  551. X    int i; struct Freenode *t;
  552. X
  553. X    if(fl->head == (struct Freenode *) NULL) {    
  554. X    t = (struct Freenode *)myalloc(sqrt_nsites * fl->nodesize);
  555. X    for(i=0; i<sqrt_nsites; i+=1)     
  556. X        makefree((struct Freenode *)((char *)t+i*fl->nodesize), fl);
  557. X    }
  558. X    t = fl->head;
  559. X    fl->head = (fl->head)->nextfree;
  560. X    return((char *)t);
  561. X}
  562. X
  563. Xmakefree(curr,fl)
  564. Xstruct Freenode *curr;
  565. Xstruct Freelist *fl;
  566. X{
  567. X    curr->nextfree = fl->head;
  568. X    fl->head = curr;
  569. X}
  570. X
  571. X#define MAXALLOCS (8 * MAXSITES)
  572. Xint total_alloc, num_allocs;
  573. Xchar *locations[MAXALLOCS];
  574. X
  575. Xchar *myalloc(n)
  576. Xunsigned n;
  577. X{
  578. X    char *t;
  579. X    if ((t=malloc(n)) == (char *) 0) {
  580. X    fprintf(stderr,"out of memory processing site %d (%d bytes in use)\n",
  581. X        siteidx, total_alloc);
  582. X        exit();
  583. X    }
  584. X    total_alloc += n;
  585. X    locations[num_allocs++] = t;
  586. X    return(t);
  587. X}
  588. X
  589. Xvoid 
  590. Xmyfreeall()
  591. X{
  592. Xint k;
  593. X
  594. X    for (k = 0; k < num_allocs; k++)
  595. X    free (locations [k]);
  596. X/*
  597. X    printf ("freed %d allocs (%d bytes)\n", num_allocs, total_alloc);
  598. X*/
  599. X    num_allocs = total_alloc = 0;
  600. X}
  601. END_OF_FILE
  602.   if test 1212 -ne `wc -c <'memory.c'`; then
  603.     echo shar: \"'memory.c'\" unpacked with wrong size!
  604.   fi
  605.   # end of 'memory.c'
  606. fi
  607. if test -f 'vordefs.h' -a "${1}" != "-c" ; then 
  608.   echo shar: Will not clobber existing file \"'vordefs.h'\"
  609. else
  610.   echo shar: Extracting \"'vordefs.h'\" \(3110 characters\)
  611.   sed "s/^X//" >'vordefs.h' <<'END_OF_FILE'
  612. X#ifndef NULL
  613. X#define NULL 0
  614. X#endif
  615. X
  616. X#define DELETED -2
  617. X
  618. X#define MAXSITES 4096
  619. X
  620. X#define le 0
  621. X#define re 1
  622. X
  623. Xextern struct Site *(*next)();
  624. Xextern int triangulate, sorted, plot, vrdebug, outputmode;
  625. Xextern float vxmin, vxmax, vymin, vymax, vdeltax, vdeltay;
  626. Xextern float pxmin, pxmax, pymin, pymax;
  627. X
  628. Xextern char execdir[];        /* from voronoi.c */
  629. X
  630. Xextern int numvedges;
  631. X
  632. Xextern int total_alloc;        /* memory.c */
  633. Xextern int menu;        /* menus.c */
  634. X
  635. Xextern float randr(float, float);
  636. X
  637. X/* GL DRAWING STUFF */
  638. X
  639. X/* vertex: x, y */
  640. Xstruct vertstruct {
  641. X    float x, y;
  642. X    int vpid;
  643. X    };
  644. X
  645. X/* vertex id w/neighbors */
  646. Xstruct nvertstruct {
  647. X    int nbr1, nbr2, onhull;
  648. X    int vpid;
  649. X    };
  650. X
  651. X/* vertex: x, y, theta */
  652. Xstruct vertthetastruct {
  653. X    float x, y, theta;
  654. X    int e1, e2;
  655. X    };
  656. X
  657. X/* edge: CLIPPED to reasonable bounds */
  658. Xstruct edgestruct {
  659. X    float x1, y1, x2, y2;
  660. X    int nbr1, nbr2;
  661. X    float xm, ym;        /* halfway between inducing voronoi sites */
  662. X    };
  663. X
  664. Xtypedef struct vertstruct VERT;
  665. Xtypedef struct nvertstruct NVERT;
  666. Xtypedef struct vertthetastruct VERTTHETA;
  667. Xtypedef struct edgestruct EDGE;
  668. X
  669. X/* triangle: holds POINTERS to three verts */
  670. Xstruct tristruct {
  671. X    VERT *v1, *v2, *v3;
  672. X    };
  673. X
  674. Xstruct circstruct {
  675. X    float cx, cy, r;
  676. X    int nbr1, nbr2, nbr3;
  677. X    };
  678. X
  679. Xtypedef struct tristruct TRI;
  680. Xtypedef struct circstruct CIRC;
  681. X
  682. X#define MAXVERTS (3 * MAXSITES)
  683. X#define MAXEDGES (2 * MAXSITES)
  684. X#define MAXTRIS  (MAXEDGES)
  685. X
  686. Xextern VERT GLsites[MAXVERTS];
  687. Xextern VERT verts[MAXVERTS];
  688. Xextern EDGE vedges[MAXEDGES];
  689. Xextern NVERT chverts[MAXVERTS];
  690. Xextern TRI  tris[MAXTRIS];
  691. Xextern CIRC circles[MAXTRIS];
  692. X
  693. X/* END GL DRAWING STUFF */
  694. X
  695. Xstruct    Freenode    {
  696. X    struct Freenode *nextfree;
  697. X};
  698. X
  699. Xstruct    Freelist    {
  700. X    struct Freenode *head;
  701. X    int    nodesize;
  702. X};
  703. X
  704. Xchar *getfree();
  705. Xchar *malloc();
  706. Xchar *myalloc();
  707. X
  708. Xstruct Point {
  709. X    float x,y;
  710. X};
  711. X
  712. X/* structure used both for sites and for vertices */
  713. Xstruct Site {
  714. X    struct Point coord;
  715. X    int sitenbr;
  716. X    int refcnt;
  717. X};
  718. X
  719. Xtypedef struct Site SITE;
  720. X
  721. Xstruct Edge {
  722. X    float a,b,c;
  723. X    struct Site *ep[2];
  724. X    struct Site    *reg[2];
  725. X    int    edgenbr;
  726. X};
  727. X
  728. Xextern struct Site *sites;
  729. Xextern int nsites;
  730. Xextern int siteidx;
  731. Xextern int sqrt_nsites;
  732. Xextern int nvertices;
  733. Xextern struct Freelist sfl;
  734. Xextern struct Site *bottomsite;
  735. X
  736. Xextern struct Site *nextone();        /* from voronoi.c */
  737. X
  738. Xextern int nedges;
  739. Xextern struct    Freelist efl;
  740. X
  741. Xvoid v_endpoint();
  742. Xint has_endpoint(),right_of();
  743. Xstruct Site *sintersect();
  744. Xfloat dist();
  745. Xstruct Point PQ_min();
  746. Xstruct Halfedge *PQextractmin();
  747. Xstruct Edge *bisect();
  748. X
  749. Xstruct Halfedge {
  750. X    struct Halfedge *ELleft, *ELright;
  751. X    struct Edge    *ELedge;
  752. X    int    ELrefcnt;
  753. X    char ELpm;
  754. X    struct Site    *vertex;
  755. X    float ystar;
  756. X    struct Halfedge *PQnext;
  757. X};
  758. X
  759. Xextern struct Freelist    hfl;
  760. Xextern struct Halfedge *ELleftend, *ELrightend;
  761. Xextern int ELhashsize;
  762. Xextern struct Halfedge **ELhash;
  763. X
  764. Xstruct Halfedge *HEcreate(), *ELleft(), *ELright(), *ELleftbnd();
  765. Xstruct Site *leftreg(), *rightreg();
  766. X
  767. Xextern int PQhashsize;
  768. Xextern struct Halfedge *PQhash;
  769. Xextern int PQcount;
  770. Xextern int PQmin;
  771. X
  772. Xint PQempty();
  773. Xstruct Halfedge *PQfind();
  774. END_OF_FILE
  775.   if test 3110 -ne `wc -c <'vordefs.h'`; then
  776.     echo shar: \"'vordefs.h'\" unpacked with wrong size!
  777.   fi
  778.   # end of 'vordefs.h'
  779. fi
  780. if test -f 'voronoi.c' -a "${1}" != "-c" ; then 
  781.   echo shar: Will not clobber existing file \"'voronoi.c'\"
  782. else
  783.   echo shar: Extracting \"'voronoi.c'\" \(4483 characters\)
  784.   sed "s/^X//" >'voronoi.c' <<'END_OF_FILE'
  785. X#include <stdio.h>
  786. X#include <math.h>
  787. X#include "vordefs.h"
  788. X
  789. X#define FALSE (0)
  790. X#define TRUE  (1)
  791. X
  792. Xint triangulate = FALSE, sorted, plot, vrdebug = FALSE, randmode, outputmode;
  793. Xfloat vxmin, vxmax, vymin, vymax, vdeltax, vdeltay;
  794. X
  795. Xchar execdir[80];
  796. X
  797. Xstruct Site _sites[MAXSITES], *sites = _sites;
  798. X
  799. Xint nsites;
  800. Xint siteidx;
  801. Xint sqrt_nsites;
  802. Xint nvertices;
  803. Xstruct Freelist sfl;
  804. Xstruct Site *bottomsite;
  805. X
  806. Xint nedges;
  807. Xstruct    Freelist efl;
  808. X
  809. Xstruct Freelist    hfl;
  810. Xstruct Halfedge *ELleftend, *ELrightend;
  811. Xint ELhashsize;
  812. Xstruct Halfedge **ELhash;
  813. X
  814. Xint PQhashsize;
  815. Xstruct Halfedge *PQhash;
  816. Xint PQcount;
  817. Xint PQmin;
  818. X
  819. X/* sort sites on y, then x, coord */
  820. Xint scomp(s1,s2)
  821. Xstruct Point *s1,*s2;
  822. X{
  823. X    if(s1->y < s2->y) return(-1);
  824. X    if(s1->y > s2->y) return(1);
  825. X    if(s1->x < s2->x) return(-1);
  826. X    if(s1->x > s2->x) return(1);
  827. X    return(0);
  828. X}
  829. X
  830. X/* sort GLsites on y, then x, coord */
  831. Xint GLscomp(s1,s2)
  832. XVERT *s1,*s2;
  833. X{
  834. X    if(s1->y < s2->y) return(-1);
  835. X    if(s1->y > s2->y) return(1);
  836. X    if(s1->x < s2->x) return(-1);
  837. X    if(s1->x > s2->x) return(1);
  838. X    return(0);
  839. X}
  840. X
  841. X/* return a single in-storage site */
  842. Xstruct Site *
  843. Xnextone()
  844. X{
  845. X    if(siteidx < nsites)
  846. X    return (&sites[siteidx++]);
  847. X    else
  848. X    return( (struct Site *)NULL);
  849. X}
  850. X
  851. XsortGLsites()
  852. X{
  853. Xfloat vx, vy;
  854. Xint k, sid;
  855. Xchar *a = NULL;
  856. Xfloat dx, dy;
  857. X
  858. X    qsort((char *)GLsites, nsites, sizeof (VERT), GLscomp);
  859. X
  860. X#ifdef EXCISE
  861. X    /* excise any coincident sites */
  862. X    for (k = sid = 0; k < nsites; k++)    {
  863. X    if (k == 0 || (GLsites[k-1].y != GLsites[k].y) || (GLsites[k-1].x != GLsites[k].x)) {
  864. X        GLsites[sid  ].x = GLsites[k].x;
  865. X        GLsites[sid++].y = GLsites[k].y;
  866. X        }
  867. X    }
  868. X
  869. X    if (sid != nsites)    {
  870. X    fprintf (stderr, "voronoi: excised %d coincident sites\n", nsites - sid);
  871. X    nsites = sid;
  872. X    }
  873. X#endif
  874. X}
  875. X
  876. X/* implicit parameters: nsites, sqrt_nsites, xmin, xmax, ymin, ymax,
  877. X   deltax, deltay (can all be estimates).
  878. X   Performance suffers if they are wrong; better to make nsites,
  879. X   deltax, and deltay too big than too small.  (?) */
  880. Xvoronoi (nextsite)
  881. Xstruct Site *(*nextsite)();
  882. X{
  883. Xstruct Site *newsite, *bot, *top, *temp, *p;
  884. Xstruct Site *v;
  885. Xstruct Point newintstar;
  886. Xint pm;
  887. Xstruct Halfedge *lbnd, *rbnd, *llbnd, *rrbnd, *bisector;
  888. Xstruct Edge *e;
  889. X
  890. X    myfreeall ();
  891. X
  892. X    if (nsites <= 1)
  893. X    return;
  894. X
  895. X    freeinit(&sfl, sizeof (struct Site));
  896. X
  897. X    /* bboxinit();  */        /* copies static array into nsites */
  898. X    geominit();            /* internal use of deltax, deltay  */
  899. X
  900. X    PQinitialize();
  901. X    bottomsite = (*nextsite)();
  902. X    out_site(bottomsite);
  903. X    ELinitialize();
  904. X
  905. X    newsite = (*nextsite)();
  906. X    while(1) {
  907. X    if(!PQempty()) newintstar = PQ_min();
  908. X/* new site is smallest */
  909. X    if (newsite != (struct Site *)NULL && (PQempty() 
  910. X         || newsite->coord.y < newintstar.y
  911. X             || (newsite->coord.y == newintstar.y 
  912. X                 && newsite->coord.x < newintstar.x))) {
  913. X        out_site(newsite);
  914. X        lbnd = ELleftbnd(&(newsite->coord));
  915. X        rbnd = ELright(lbnd);
  916. X        bot = rightreg(lbnd);
  917. X        e = bisect(bot, newsite);
  918. X        bisector = HEcreate(e, le);
  919. X        ELinsert(lbnd, bisector);
  920. X        if ((p = sintersect(lbnd, bisector)) != (struct Site *) NULL) {
  921. X        PQdelete(lbnd);
  922. X        PQinsert(lbnd, p, dist(p,newsite));
  923. X        }
  924. X        lbnd = bisector;
  925. X        bisector = HEcreate(e, re);
  926. X        ELinsert(lbnd, bisector);
  927. X        if ((p = sintersect(bisector, rbnd)) != (struct Site *) NULL) {
  928. X        PQinsert(bisector, p, dist(p,newsite));    
  929. X        }
  930. X        newsite = (*nextsite)();    
  931. X    } else if (!PQempty()) {
  932. X    /* intersection is smallest */
  933. X        lbnd = PQextractmin();
  934. X        llbnd = ELleft(lbnd);
  935. X        rbnd = ELright(lbnd);
  936. X        rrbnd = ELright(rbnd);
  937. X        bot = leftreg(lbnd);
  938. X        top = rightreg(rbnd);
  939. X        out_triple(bot, top, rightreg(lbnd));
  940. X        v = lbnd->vertex;
  941. X        makevertex(v);
  942. X        v_endpoint(lbnd->ELedge,lbnd->ELpm,v);
  943. X        v_endpoint(rbnd->ELedge,rbnd->ELpm,v);
  944. X        ELdelete(lbnd); 
  945. X        PQdelete(rbnd);
  946. X        ELdelete(rbnd); 
  947. X        pm = le;
  948. X        if (bot->coord.y > top->coord.y) {    
  949. X        temp = bot; 
  950. X        bot = top; 
  951. X        top = temp; 
  952. X        pm = re;
  953. X        }
  954. X        e = bisect(bot, top);
  955. X        bisector = HEcreate(e, pm);
  956. X        ELinsert(llbnd, bisector);
  957. X        v_endpoint(e, re-pm, v);
  958. X        deref(v);
  959. X        if((p = sintersect(llbnd, bisector)) != (struct Site *) NULL) {
  960. X        PQdelete(llbnd);
  961. X        PQinsert(llbnd, p, dist(p,bot));
  962. X        }
  963. X        if((p = sintersect(bisector, rrbnd)) != (struct Site *) NULL) 
  964. X        PQinsert(bisector, p, dist(p,bot));
  965. X    } else 
  966. X        break;
  967. X    }
  968. X
  969. X    for(lbnd=ELright(ELleftend); lbnd != ELrightend; lbnd=ELright(lbnd)) {
  970. X    e = lbnd->ELedge;
  971. X    out_ep(e);
  972. X        }
  973. X}
  974. X
  975. X
  976. END_OF_FILE
  977.   if test 4483 -ne `wc -c <'voronoi.c'`; then
  978.     echo shar: \"'voronoi.c'\" unpacked with wrong size!
  979.   fi
  980.   # end of 'voronoi.c'
  981. fi
  982. if test -f 'voronoi.h' -a "${1}" != "-c" ; then 
  983.   echo shar: Will not clobber existing file \"'voronoi.h'\"
  984. else
  985.   echo shar: Extracting \"'voronoi.h'\" \(2977 characters\)
  986.   sed "s/^X//" >'voronoi.h' <<'END_OF_FILE'
  987. X#define MAXSITES 4096
  988. X
  989. X/* GL DRAWING STUFF */
  990. X
  991. X/* vertex: x, y */
  992. Xstruct vertstruct {
  993. X    float x, y;
  994. X    int vpid;
  995. X    };
  996. X
  997. X/* vertex id w/neighbors */
  998. Xstruct nvertstruct {
  999. X    int nbr1, nbr2, onhull;
  1000. X    int vpid;
  1001. X    };
  1002. X
  1003. X/* vertex: x, y, theta */
  1004. Xstruct vertthetastruct {
  1005. X    float x, y, theta;
  1006. X    int e1, e2;
  1007. X    };
  1008. X
  1009. X/* edge: CLIPPED to reasonable bounds */
  1010. Xstruct edgestruct {
  1011. X    float x1, y1, x2, y2;
  1012. X    int nbr1, nbr2;
  1013. X    float xm, ym;        /* halfway between inducing voronoi sites */
  1014. X    };
  1015. X
  1016. Xtypedef struct vertstruct VERT;
  1017. Xtypedef struct nvertstruct NVERT;
  1018. Xtypedef struct vertthetastruct VERTTHETA;
  1019. Xtypedef struct edgestruct EDGE;
  1020. X
  1021. X/* triangle: holds POINTERS to three verts */
  1022. Xstruct tristruct {
  1023. X    VERT *v1, *v2, *v3;
  1024. X    };
  1025. X
  1026. Xstruct circstruct {
  1027. X    float cx, cy, r;
  1028. X    int nbr1, nbr2, nbr3;
  1029. X    };
  1030. X
  1031. Xtypedef struct tristruct TRI;
  1032. Xtypedef struct circstruct CIRC;
  1033. X
  1034. X#define MAXVERTS (3 * MAXSITES)
  1035. X#define MAXEDGES (2 * MAXSITES)
  1036. X#define MAXTRIS  (MAXEDGES)
  1037. X
  1038. Xextern VERT GLsites[MAXVERTS];
  1039. Xextern VERT verts[MAXVERTS];
  1040. Xextern EDGE vedges[MAXEDGES];
  1041. Xextern NVERT chverts[MAXVERTS];
  1042. Xextern TRI  tris[MAXTRIS];
  1043. Xextern CIRC circles[MAXTRIS];
  1044. X
  1045. X/* load_vsites(): 
  1046. X    accept the n voronoi sites (x_n, y_n)
  1047. X    calculate and store the voronoi diagram over the n sites,
  1048. X    clipping all infinite edges to bbox: [xmin, ymin, xmax, ymax].
  1049. X    
  1050. X    note: if (xmin,ymin,xmax,ymax are all == 0.0), OR
  1051. X    if these do not enclose the data, a bounding box
  1052. X     will be computed over the input.
  1053. X
  1054. X    returns:
  1055. X    -1 if error
  1056. X     0 otherwise
  1057. X*/
  1058. Xint
  1059. Xload_vsites (
  1060. X    int n,
  1061. X    float usites[][2],    /* sites in x,y order */
  1062. X    float uxmin, float uymin, float uxmax, float uymax);
  1063. X
  1064. X/*
  1065. X    find_vregion(sid, plen, pverts)
  1066. X    given a site id 'sid' from 0..nsites-1 inclusive, 
  1067. X    returns the voronoi polygon associated with that site
  1068. X    in the array 'pverts', and its length on call stack.
  1069. X
  1070. X    the vertices are returned in counterclockwise order.
  1071. X
  1072. X    returns:
  1073. X    -1 if error condition
  1074. X    plen > 2 [i.e., the # of verts in the voronoi polygon] otherwise
  1075. X*/
  1076. Xint
  1077. Xfind_vregion (
  1078. X    int vsid,
  1079. X    float pverts[][2]);
  1080. X
  1081. X/*
  1082. X    int
  1083. X    find_dtriangles (**dtris)
  1084. X
  1085. X    returns:
  1086. X    -1 if error condition, *dtris == NULL
  1087. X    o/wise, # of delaunay triangles, *dtris == array of TRIS (see voronoi.h)
  1088. X*/
  1089. Xint
  1090. Xfind_dtriangles (
  1091. X    TRI **dtris);
  1092. X
  1093. X/*
  1094. X    int
  1095. X    find_dtadjacency (*(int[][2]))
  1096. X
  1097. X    returns:
  1098. X    -1 if error condition, *dtadj == NULL
  1099. X    o/wise, # of adjacency pairs, and all pairs
  1100. X    indices refer to triangle ids as returned by find_dtriangles()
  1101. X*/
  1102. X
  1103. Xint
  1104. Xfind_dtadjacencies (
  1105. X    int (**dtadj)[][2]);        /* pointer to array of nx2 integers */
  1106. X
  1107. X/*
  1108. X    int
  1109. X    find_convexhull (**chverts)
  1110. X
  1111. X    returns:
  1112. X    if error condition
  1113. X         *chverts == NULL
  1114. X        returns -1 
  1115. X    o/wise, 
  1116. X        *chverts == array of named VERTs (see voronoi.h), in order around convex hull
  1117. X        *chvert[k].vpid == index of point in point set given to load_vertices()
  1118. X        returns # of convex hull vertices
  1119. X*/
  1120. Xint
  1121. Xfind_convexhull(
  1122. X    NVERT **chvertices);
  1123. END_OF_FILE
  1124.   if test 2977 -ne `wc -c <'voronoi.h'`; then
  1125.     echo shar: \"'voronoi.h'\" unpacked with wrong size!
  1126.   fi
  1127.   # end of 'voronoi.h'
  1128. fi
  1129. if test -f 'vortest.c' -a "${1}" != "-c" ; then 
  1130.   echo shar: Will not clobber existing file \"'vortest.c'\"
  1131. else
  1132.   echo shar: Extracting \"'vortest.c'\" \(3292 characters\)
  1133.   sed "s/^X//" >'vortest.c' <<'END_OF_FILE'
  1134. X/*
  1135. X
  1136. Xcompile as cc -float -g -prototypes -c vortest2.c
  1137. X
  1138. Xlink as cc -o vortest2 vortest2.o ~/base/lib/libvor.a -lm
  1139. X
  1140. X*/
  1141. X
  1142. X#include <stdio.h>
  1143. X#include "voronoi.h"
  1144. X
  1145. X#define E    (0.02)
  1146. X
  1147. X/* example for use of voronoi region package    */
  1148. X/*  create data in xy float array        */
  1149. X/*  call load_vsites() to create vor diagram    */
  1150. X/*  call find_vregion() to query structure    */
  1151. X
  1152. Xfloat data[][2] = {
  1153. X            {-1.0448985, 0.6952569},
  1154. X            {-0.2643085,-0.1562872},
  1155. X            {-0.3617359,-0.8812830},
  1156. X            {-0.9136937,-0.6788232},
  1157. X            {-0.9266945, 0.3022859},
  1158. X            {-0.3424, 0.6394},
  1159. X            {-0.1645, 0.895443},
  1160. X            {-0.9345435, 0.4523450},
  1161. X
  1162. X            /* sentinel entry */
  1163. X            { -9999.0, -9999.0 }
  1164. X          };
  1165. X
  1166. Xmain()
  1167. X{
  1168. Xint n=0, sid, vid, plen;
  1169. Xfloat pverts[256][2];
  1170. Xint ntris, tid, nchverts;
  1171. XTRI *dtris;
  1172. XNVERT *chverts;
  1173. Xchar nstr[32];
  1174. X
  1175. X    /* count the number of sites in data array (sizeof() should work, but doesn't) */
  1176. X    while (data[n][0] != -9999.0 || data[n][1] != -9999.0)
  1177. X    n++;
  1178. X
  1179. X    printf ("found %d vertices in data:\n", n);
  1180. X    for (sid = 0; sid < n; sid++)
  1181. X    printf ("site %d:\t(%f, %f)\n", sid, data[sid][0], data[sid][1]);
  1182. X
  1183. X    printf ("calling load_vsites() with user bbox\n");
  1184. X    load_vsites (n, data, -2.0, -2.0, 2.0, 2.0);
  1185. X
  1186. X    for (sid = 0; sid < n; sid++) {
  1187. X    plen = find_vregion (sid, pverts);
  1188. X    printf ("region of site %d has length %d\n", sid, plen);
  1189. X
  1190. X    for (vid = 0; vid < plen; vid++)
  1191. X        printf ("\t%f %f\n", pverts[vid][0], pverts[vid][1]);
  1192. X        }
  1193. X
  1194. X    ntris = find_dtriangles (&dtris);
  1195. X    for (tid = 0; tid < ntris; tid++)    {
  1196. X    printf ("delaunay triangle %d has vertices %d, %d, %d\n", 
  1197. X        tid, dtris[tid].v1->vpid, dtris[tid].v2->vpid, dtris[tid].v3->vpid);
  1198. X    printf ("\tcoords (%f, %f)  (%f, %f)  (%f, %f)\n", 
  1199. X        dtris[tid].v1->x, dtris[tid].v1->y, 
  1200. X        dtris[tid].v2->x, dtris[tid].v2->y, 
  1201. X        dtris[tid].v3->x, dtris[tid].v3->y);
  1202. X    }
  1203. X
  1204. X    nchverts = find_convexhull (&chverts);
  1205. X    for (vid = 0; vid < nchverts; vid++)
  1206. X    printf ("convex hull vertex %d has id %d [bk %d, fw %d]\n", vid, 
  1207. X        chverts[vid].vpid, chverts[vid].nbr1, chverts[vid].nbr2);
  1208. X
  1209. X    printf ("calling load_vsites() with no bbox\n");
  1210. X    load_vsites (n, data, 0.0, 0.0, 0.0, 0.0);
  1211. X
  1212. X    for (sid = 0; sid < n; sid++) {
  1213. X    plen = find_vregion (sid, pverts);
  1214. X    printf ("region of site %d has length %d\n", sid, plen);
  1215. X    for (vid = 0; vid < plen; vid++)
  1216. X        printf ("\t%f %f\n", pverts[vid][0], pverts[vid][1]);
  1217. X    }
  1218. X
  1219. X    ntris = find_dtriangles (&dtris);
  1220. X    for (tid = 0; tid < ntris; tid++)    {
  1221. X    printf ("delaunay triangle %d has vertices %d, %d, %d\n", 
  1222. X        tid, dtris[tid].v1->vpid, dtris[tid].v2->vpid, dtris[tid].v3->vpid);
  1223. X    printf ("\tcoords (%f, %f)  (%f, %f)  (%f, %f)\n", 
  1224. X        dtris[tid].v1->x, dtris[tid].v1->y, 
  1225. X        dtris[tid].v2->x, dtris[tid].v2->y, 
  1226. X        dtris[tid].v3->x, dtris[tid].v3->y);
  1227. X    }
  1228. X
  1229. X    nchverts = find_convexhull (&chverts);
  1230. X    for (vid = 0; vid < nchverts; vid++)    {
  1231. X    printf ("convex hull vertex %d has id %d [bk %d, fw %d]\n", vid, 
  1232. X        chverts[vid].vpid, chverts[vid].nbr1, chverts[vid].nbr2);
  1233. X    }
  1234. X
  1235. X    {
  1236. X    int k, nadjs, (*adjs)[][2];        /* pointer  to nx2 array of ints */
  1237. X
  1238. X    nadjs = find_dtadjacencies (&adjs);
  1239. X
  1240. X    if (nadjs > 0)  {
  1241. X    for (k = 0; k < nadjs; k++) {    
  1242. X        printf ("found adj between tri %d and %d\n", (*adjs)[k][0], (*adjs)[k][1]);
  1243. X        } 
  1244. X    }
  1245. X
  1246. X    }
  1247. X    
  1248. X    exit(0);
  1249. X}
  1250. X
  1251. X
  1252. END_OF_FILE
  1253.   if test 3292 -ne `wc -c <'vortest.c'`; then
  1254.     echo shar: \"'vortest.c'\" unpacked with wrong size!
  1255.   fi
  1256.   # end of 'vortest.c'
  1257. fi
  1258. if test -f 'vregion.c' -a "${1}" != "-c" ; then 
  1259.   echo shar: Will not clobber existing file \"'vregion.c'\"
  1260. else
  1261.   echo shar: Extracting \"'vregion.c'\" \(24021 characters\)
  1262.   sed "s/^X//" >'vregion.c' <<'END_OF_FILE'
  1263. X#include <stdio.h>
  1264. X#include <math.h>
  1265. X#include <assert.h>
  1266. X#include "vordefs.h"
  1267. X
  1268. X#define LBND 0
  1269. X#define BBND 1
  1270. X#define RBND 2
  1271. X#define TBND 3
  1272. X
  1273. X#define FALSE (0)
  1274. X#define TRUE  (1)
  1275. X
  1276. X#define ABS(A) ((A) < 0 ? (-(A)) : (A))
  1277. X#define MAX(a,b) ((a) > (b) ? (a) : (b))
  1278. X#define MIN(a,b) ((a) < (b) ? (a) : (b))
  1279. X#define AVG(a,b) (((a)+(b))*0.5)
  1280. X
  1281. X/* left, right, top bottom */
  1282. X#define NBOUND(x,y) (x >= Pxmax ? RBND : (x <= Pxmin ? LBND : (y >= Pymax ? TBND : (y <= Pymin ? BBND : -1))))
  1283. X
  1284. X#define BBOX_THERE() ((pxmin == txmin) && (pxmax == txmax) && (pymin == tymin) && (pymax && pymax))
  1285. X#define BBOX_NOT_THERE() (!BBOX_THERE())
  1286. X
  1287. Xstatic float Pxmin, Pxmax, Pymin, Pymax;    /* floating point tolerance values */
  1288. Xstatic float pxmin = 1E10, pxmax = -1E10, pymin = 1E10, pymax = -1E10;
  1289. X
  1290. X/* space for theta after x*y* */
  1291. Xstatic float xminymin[3], xminymax[3], xmaxymax[3], xmaxymin[3];
  1292. X
  1293. X/* these point to the x*y* */
  1294. Xstatic VERTTHETA *corner[4];
  1295. X
  1296. Xstatic int numverts = 0, numvedges = 0, numtris;
  1297. X
  1298. X/* sites[i].coord.x,y defined and sorted in main() */
  1299. X
  1300. XVERT    GLsites[MAXVERTS];
  1301. XVERT    Usites[MAXVERTS];
  1302. X/*     static int nUsites; */
  1303. X
  1304. Xstatic VERT verts[MAXVERTS];
  1305. Xstatic EDGE vedges[MAXEDGES];
  1306. Xstatic TRI  tris[MAXTRIS];
  1307. Xstatic int  inverse[MAXVERTS];
  1308. Xstatic NVERT chverts[MAXVERTS];
  1309. Xstatic NVERT uchverts[MAXVERTS];
  1310. X
  1311. X
  1312. X/* null out extern refs */
  1313. Xvoid out_site(struct Site *s){}
  1314. Xvoid out_bisector(struct Edge *e){}
  1315. X
  1316. Xstatic int
  1317. Xclip_line(
  1318. X    struct Edge *e)
  1319. X{
  1320. Xstruct Site *s1, *s2;
  1321. Xstruct Site *r1, *r2;
  1322. Xfloat x1,x2,y1,y2;
  1323. X
  1324. X    if(e->a == 1.0 && e->b >= 0.0) {    
  1325. X    s1 = e->ep[1];
  1326. X    s2 = e->ep[0];
  1327. X
  1328. X    r1 = e->reg[1];
  1329. X    r2 = e->reg[0];
  1330. X    } else {    
  1331. X    s1 = e->ep[0];
  1332. X    s2 = e->ep[1];
  1333. X
  1334. X    r1 = e->reg[0];
  1335. X    r2 = e->reg[1];
  1336. X    }
  1337. X
  1338. X    /* mark convex hull sites and add edge to ch list */
  1339. X    if (s1 == NULL || s2 == NULL)   {
  1340. X    NVERT *vA, *vB;
  1341. X    int A, B;
  1342. X
  1343. X        vA = &chverts[A = r1->sitenbr];
  1344. X        vB = &chverts[B = r2->sitenbr];
  1345. X    
  1346. X        vA->onhull = vB->onhull = TRUE;
  1347. X
  1348. X        if (vA->nbr1 == -1)
  1349. X            vA->nbr1 = B;
  1350. X        else if (vA->nbr2 == -1)    {
  1351. X        if (vA->nbr1 != B)
  1352. X        vA->nbr2 = B;
  1353. X        }
  1354. X
  1355. X        if (vB->nbr1 == -1)
  1356. X            vB->nbr1 = A;
  1357. X        else if (vB->nbr2 == -1)    {
  1358. X        if (vB->nbr1 != A)
  1359. X        vB->nbr2 = A;
  1360. X        }
  1361. X/*
  1362. X        if (vrdebug)
  1363. X            printf ("setting hull on %d, %d\n", r1->sitenbr, r2->sitenbr);
  1364. X*/
  1365. X        }
  1366. X
  1367. X    if(e->a == 1.0) {
  1368. X    y1 = pymin;
  1369. X    if (s1!=(struct Site *)NULL && s1->coord.y > pymin)
  1370. X        y1 = s1->coord.y;
  1371. X    if(y1>pymax)
  1372. X        return;
  1373. X    x1 = e->c - e->b * y1;
  1374. X    y2 = pymax;
  1375. X    if (s2!=(struct Site *)NULL && s2->coord.y < pymax)
  1376. X        y2 = s2->coord.y;
  1377. X    if(y2<pymin)
  1378. X        return(0);
  1379. X    x2 = e->c - e->b * y2;
  1380. X    if ((x1> pxmax && x2>pxmax) || (x1<pxmin && x2<pxmin)) 
  1381. X        return;
  1382. X    if(x1> pxmax) {
  1383. X        x1 = pxmax;
  1384. X        y1 = (e->c - x1)/e->b;
  1385. X    }
  1386. X    if(x1<pxmin) {
  1387. X        x1 = pxmin;
  1388. X        y1 = (e->c - x1)/e->b;
  1389. X    }
  1390. X    if(x2>pxmax) {
  1391. X        x2 = pxmax;
  1392. X        y2 = (e->c - x2)/e->b;
  1393. X    }
  1394. X    if(x2<pxmin) {
  1395. X        x2 = pxmin;
  1396. X        y2 = (e->c - x2)/e->b;
  1397. X    }
  1398. X    } else {
  1399. X    x1 = pxmin;
  1400. X    if (s1!=(struct Site *)NULL && s1->coord.x > pxmin) 
  1401. X        x1 = s1->coord.x;
  1402. X    if(x1>pxmax)
  1403. X        return(0);
  1404. X    y1 = e->c - e->a * x1;
  1405. X    x2 = pxmax;
  1406. X    if (s2!=(struct Site *)NULL && s2->coord.x < pxmax)
  1407. X        x2 = s2->coord.x;
  1408. X    if(x2<pxmin)
  1409. X        return(0);
  1410. X    y2 = e->c - e->a * x2;
  1411. X    if ((y1> pymax && y2>pymax) || (y1<pymin && y2<pymin))
  1412. X        return(0);
  1413. X    if(y1> pymax) {
  1414. X        y1 = pymax;
  1415. X        x1 = (e->c - y1)/e->a;
  1416. X    }
  1417. X    if(y1<pymin) {
  1418. X        y1 = pymin;
  1419. X        x1 = (e->c - y1)/e->a;
  1420. X    }
  1421. X    if(y2>pymax) {
  1422. X        y2 = pymax;
  1423. X        x2 = (e->c - y2)/e->a;
  1424. X    }
  1425. X    if(y2<pymin) {
  1426. X        y2 = pymin;
  1427. X        x2 = (e->c - y2)/e->a;
  1428. X    }
  1429. X    }
  1430. X
  1431. X/*  fprintf (stderr, "clip_line(): edge %d is (%10.7f, %10.7f) to (%10.7f, %10.7f)\n", numvedges, x1, y1, x2, y2);*/
  1432. X
  1433. X    if (!triangulate)    {
  1434. X    vedges[numvedges].x1 = x1;
  1435. X    vedges[numvedges].y1 = y1;
  1436. X
  1437. X    vedges[numvedges].x2 = x2;
  1438. X    vedges[numvedges].y2 = y2;
  1439. X
  1440. X    vedges[numvedges].nbr1 = (r1 != NULL ? r1->sitenbr : -9998);
  1441. X    vedges[numvedges].nbr2 = (r2 != NULL ? r2->sitenbr : -9999);
  1442. X
  1443. X    if (r1 != NULL && r2 != NULL)    {
  1444. X        vedges[numvedges].xm = AVG (r1->coord.x, r2->coord.x);
  1445. X        vedges[numvedges].ym = AVG (r1->coord.y, r2->coord.y);
  1446. X        }
  1447. X
  1448. X    if (vrdebug)
  1449. X        printf ("clip_line puts edge induced by %d and %d\n", r1->sitenbr, r2->sitenbr);
  1450. X
  1451. X    if (numvedges < MAXEDGES)
  1452. X        numvedges++;
  1453. X    else    {
  1454. X        fprintf (stderr, "clip_line(): edge list overflow!\n");
  1455. X        exit (-1);
  1456. X        }
  1457. X    }
  1458. X}
  1459. X
  1460. X/* extern ref */
  1461. Xvoid 
  1462. Xout_ep(
  1463. X    struct Edge *e)
  1464. X{
  1465. X    if(!triangulate)
  1466. X    clip_line(e);
  1467. X
  1468. X    if(vrdebug)    {
  1469. X    printf("out_ep(): edge %d", e->edgenbr);
  1470. X    printf(" ep %d", e->ep[le] != (struct Site *)NULL ? e->ep[le]->sitenbr : -1);
  1471. X    printf(" ep %d", e->ep[re] != (struct Site *)NULL ? e->ep[re]->sitenbr : -1);
  1472. X    printf(" reg %d", e->reg[le] != (struct Site *)NULL ? e->reg[le]->sitenbr : -1);
  1473. X    printf(" reg %d\n", e->reg[re] != (struct Site *)NULL ? e->reg[re]->sitenbr : -1);
  1474. X    }
  1475. X}
  1476. X
  1477. X/* extern ref */
  1478. Xvoid
  1479. Xout_vertex(
  1480. X    struct Site *v)
  1481. X{
  1482. X    if (!triangulate)    {
  1483. X    verts[numverts].x = v->coord.x;
  1484. X    verts[numverts].y = v->coord.y;
  1485. X    if (numverts < MAXVERTS)
  1486. X        numverts++;
  1487. X    else    {
  1488. X        fprintf (stderr, "\nvert list overflow!");
  1489. X        exit (-1);
  1490. X        }
  1491. X    }
  1492. X
  1493. X    if(vrdebug)
  1494. X    printf("vertex(%d) at %10.7f %10.7f\n", v->sitenbr, v->coord.x, v->coord.y);
  1495. X}
  1496. X
  1497. X/* this version courtesy vel kahan */
  1498. X/* predicate: true iff point c leftof directed line ab */
  1499. X/* observation: we should use two shortest disp vectors */
  1500. Xstatic int 
  1501. XCHS_LEFTOF(float cx, float cy, float ax, float ay, float bx, float by)
  1502. X{
  1503. Xdouble dist_ab, dist_bc, dist_ca, max_dist;
  1504. Xdouble det_b, det_a, det_c;
  1505. Xdouble err_b, err_a, err_c;
  1506. X
  1507. X    /* complain if line is indeterminate */
  1508. X    if (ax == bx && ay == by)    {
  1509. X    fprintf (stderr, "indeterminate line in leftof() predicate!\n");
  1510. X    return (0);
  1511. X    }
  1512. X
  1513. X    /* detect coincidences */
  1514. X    if ((cx == ax && cy == ay) || (cx == bx && cy == by))
  1515. X    return (0);
  1516. X
  1517. X    /* find pairwise distances */
  1518. X    dist_ab = sqrt ((bx - ax) * (bx - ax) + (by - ay) * (by - ay));
  1519. X    dist_bc = sqrt ((cx - bx) * (cx - bx) + (cy - by) * (cy - by));
  1520. X    dist_ca = sqrt ((ax - cx) * (ax - cx) + (ay - cy) * (ay - cy));
  1521. X
  1522. X    max_dist = MAX (dist_ab, MAX(dist_bc, dist_ca));
  1523. X
  1524. X    if (max_dist == dist_bc)    {
  1525. X        /* use a as a pivot point [ie., form (c-a) x (b-a)] */
  1526. X    det_a = (ax - cx) * (by - ay) - (ay - cy) * (bx - ax);
  1527. X        if (det_a == 0.0)
  1528. X        return (0);
  1529. X        err_a = (fabs((ax - cx) * (by - ay)) + fabs((ay - cy) * (bx - ax))) / det_a;
  1530. X    if ((fabs(det_a) > 1.0E-6) || (err_a < 1.0E-7))
  1531. X        return (det_a > 0.0);
  1532. X    else
  1533. X        return (0);
  1534. X    }
  1535. X    else if (max_dist == dist_ca)   {
  1536. X        /* use b as a pivot point [ie., form (a-b) x (c-b)] */
  1537. X    det_b = (cx - bx) * (ay - by) - (cy - by) * (ax - bx);
  1538. X        if (det_b == 0.0)
  1539. X        return (0);
  1540. X        err_b = (fabs((cx - bx) * (ay - by)) + fabs((cy - by) * (ax - bx))) / det_b;
  1541. X    if ((fabs(det_b) > 1.0E-6) || (err_b < 1.0E-7))
  1542. X        return (det_b > 0.0);
  1543. X    else
  1544. X        return (0);
  1545. X    }
  1546. X    else    {
  1547. X    assert (max_dist == dist_ab);
  1548. X
  1549. X        /* use c as a pivot point [ie., form (b-c) x (a-c)] */
  1550. X    det_c = (ax - cx) * (by - cy) - (ay - cy) * (bx - cx);
  1551. X        if (det_c == 0.0)
  1552. X        return (0);
  1553. X        err_c = (fabs((cx - ax) * (by - cy)) + fabs((cy - ay) * (bx - cx))) / det_c;
  1554. X    if ((fabs(det_c) > 1.0E-6) || (err_c < 1.0E-7))
  1555. X        return (det_c > 0.0);
  1556. X    else
  1557. X        return (0);
  1558. X    }
  1559. X}
  1560. X
  1561. X/* extern ref */
  1562. Xvoid
  1563. Xout_triple(
  1564. X    struct Site *s1, struct Site *s2, struct Site *s3)
  1565. X{
  1566. XVERT *tmp;
  1567. XTRI *tri;
  1568. X
  1569. X    if(triangulate) {
  1570. X    if (numtris < MAXTRIS)
  1571. X        tri = &tris[numtris++];
  1572. X    else    {
  1573. X        fprintf (stderr, "out_triple(): triangle list overflow!\n");
  1574. X        exit (-1);
  1575. X        }
  1576. X
  1577. X    tri->v1 = (VERT *)&(sites[s1->sitenbr].coord);
  1578. X    tri->v2 = (VERT *)&(sites[s2->sitenbr].coord);
  1579. X    tri->v3 = (VERT *)&(sites[s3->sitenbr].coord);
  1580. X
  1581. X    /* order the triangle ccw */
  1582. X    if (!CHS_LEFTOF (tri->v3->x, tri->v3->y, tri->v1->x, tri->v1->y, tri->v2->x, tri->v2->y))   { 
  1583. X        tmp = tri->v3;
  1584. X        tri->v3 = tri->v2;
  1585. X        tri->v2 = tmp;
  1586. X        }
  1587. X    }
  1588. X}
  1589. X
  1590. Xstatic void
  1591. Xvdinit(void)
  1592. X{
  1593. X    numverts = numvedges = numtris = 0;
  1594. X}
  1595. X
  1596. Xstatic void
  1597. Xemit_sites (
  1598. X    struct Site *vsites, int nsites)
  1599. X{
  1600. Xstatic char fname[128];
  1601. Xstatic int fid = 0;
  1602. XFILE *f;
  1603. Xint k;
  1604. X
  1605. X    sprintf (fname, "vsites.%04d", fid++);
  1606. X    if ((f = fopen(fname, "w")) != NULL)
  1607. X    fprintf (stderr, "opened file '%s' for write\n", fname);
  1608. X    else
  1609. X    fprintf (stderr, "couldn't open file '%s' for write\n", fname);    
  1610. X
  1611. X    for(k = 0; k < nsites; k++)
  1612. X    fprintf (f, "%8.6f %8.6f\n", sites[k].coord.x, sites[k].coord.y);
  1613. X
  1614. X    fclose (f);
  1615. X}
  1616. X
  1617. X
  1618. X/* here, want to copy the gl sites INTO the voronoi array */
  1619. X/* gl sites are written exactly once at beginning of time */
  1620. Xstatic void
  1621. Xbboxinit(void)
  1622. X{
  1623. Xint k;
  1624. Xfloat dx, dy, x, y;
  1625. X
  1626. X    /* get tight bounding box */
  1627. X    vxmin =  1e10;
  1628. X    vxmax = -1e10;
  1629. X
  1630. X    vymin =  1e10;
  1631. X    vymax = -1e10;
  1632. X
  1633. X    for(k = 0; k < nsites; k++) {    
  1634. X    x = sites[k].coord.x = GLsites[k].x;
  1635. X    y = sites[k].coord.y = GLsites[k].y;
  1636. X
  1637. X        sites[k].refcnt = 0;
  1638. X    sites[k].sitenbr = k;
  1639. X
  1640. X    if (x < vxmin) vxmin = x;
  1641. X    if (y < vymin) vymin = y;
  1642. X
  1643. X    if (x > vxmax) vxmax = x;
  1644. X    if (y > vymax) vymax = y;
  1645. X    }
  1646. X
  1647. X    if (vrdebug)
  1648. X    emit_sites (sites, nsites);
  1649. X
  1650. X    /* NOW: xmin, ymin, xmax, ymax EXACT, as required by voronoi() */
  1651. X    /* we shall fool with pxmin, pymin, pxmax, pymax, as used by clip() */
  1652. X
  1653. X#define EPSILON 1.0
  1654. X
  1655. X    /* compute 'loose' bounding box */
  1656. X    dx = vxmax - vxmin;
  1657. X    dx = MAX (dx, EPSILON);
  1658. X
  1659. X    dy = vymax - vymin;
  1660. X    dy = MAX (dy, EPSILON);
  1661. X
  1662. X    pxmin = vxmin - dx * 0.25;
  1663. X    pymin = vymin - dy * 0.25;
  1664. X
  1665. X    pxmax = vxmax + dx * 0.25;
  1666. X    pymax = vymax + dy * 0.25;
  1667. X
  1668. X#ifdef STUPID_C_COMPILER
  1669. X    printf ("/* xmin, ymin %10.7f %10.7f; xmax, ymax %10.7f %10.7f; */\n", vxmin, vymin, vxmax, vymax);
  1670. X    printf ("/* pxmin, pymin %10.7f %10.7f; pxmax, pymax %10.7f %10.7f; crad %10.7f; */\n", pxmin, pymin, pxmax, pymax, cradius);
  1671. X#endif
  1672. X}
  1673. X
  1674. X/* load_vsites(): 
  1675. X    accept the n voronoi sites (x_n, y_n)
  1676. X    calculate and store the voronoi diagram over the n sites,
  1677. X    clipping all infinite edges to bbox: [xmin, ymin, xmax, ymax].
  1678. X    
  1679. X    note: if (xmin,ymin,xmax,ymax are all == 0.0), OR
  1680. X    if these do not enclose the data, a bounding box
  1681. X     will be computed over the input.
  1682. X
  1683. X    returns:
  1684. X    -1 if error
  1685. X     0 otherwise
  1686. X*/
  1687. Xint
  1688. Xload_vsites (
  1689. X    int n,
  1690. X    float usites[][2],    /* sites in x,y order */
  1691. X    float uxmin, float uymin, float uxmax, float uymax)
  1692. X{
  1693. Xint k, compute_bbox, sid, tid;
  1694. Xfloat dx, dy, x, y;
  1695. X
  1696. X    if (n >= MAXSITES)    {
  1697. X    fprintf (stderr, "load_vsites(): can't handle >= %d sites.\n", MAXSITES);
  1698. X    return (-1);
  1699. X    }
  1700. X
  1701. X    compute_bbox = (uxmin == 0.0) && (uymin == 0.0) && (uxmax == 0.0) && (uymax == 0.0);
  1702. X
  1703. X    /* copy the sites into GLsites and Usites, and set global nsites */
  1704. X    for (k = 0; k < n; k++) {
  1705. X    Usites[k].x = GLsites[k].x = usites[k][0];
  1706. X    Usites[k].y = GLsites[k].y = usites[k][1];
  1707. X    /* Usites[k].vpid = */    GLsites[k].vpid = k;        /* user's integer site id */
  1708. X
  1709. X    chverts[k].nbr1 = chverts[k].nbr2 = -1;
  1710. X    chverts[k].onhull = FALSE;
  1711. X    }
  1712. X
  1713. X    /* nUsites = n; */
  1714. X    if ((nsites = n) <= 2)  {
  1715. X    for (k = 0; k < nsites; k++)    {
  1716. X        uchverts[k].vpid = k;
  1717. X        uchverts[k].nbr1 = (k-1+nsites) % nsites;
  1718. X        uchverts[k].nbr2 = (k+1+nsites) % nsites;
  1719. X        }
  1720. X    return;
  1721. X    }
  1722. X
  1723. X    /* sort GL sites lexicographically by position */
  1724. X    sortGLsites();
  1725. X
  1726. X    /* copy sorted GLsites into voronoi alg sites */
  1727. X    bboxinit();
  1728. X
  1729. X    /* now, if user punted on bbox calculation, OR if user bbox does not truly enclose
  1730. X       user data, we use our bbox (computed in initbbox).  otherwise we take the user's. */
  1731. X    if (!(compute_bbox || uxmin > vxmin || uymin > vymin || uxmax < vxmax || uymax < vymax))    {
  1732. X    pxmin = uxmin;
  1733. X    pymin = uymin;
  1734. X
  1735. X    pxmax = uxmax;
  1736. X    pymax = uymax;
  1737. X    }
  1738. X
  1739. X    xminymax [0] = xminymin[0] = pxmin;
  1740. X    xminymin [1] = xmaxymin[1] = pymin;
  1741. X
  1742. X    xmaxymax [0] = xmaxymin[0] = pxmax;
  1743. X    xmaxymax [1] = xminymax[1] = pymax;
  1744. X
  1745. X    corner[0] = (VERTTHETA *)xminymin;
  1746. X    corner[1] = (VERTTHETA *)xmaxymin;
  1747. X    corner[2] = (VERTTHETA *)xmaxymax;
  1748. X    corner[3] = (VERTTHETA *)xminymax;
  1749. X
  1750. X    /* now: set the floating point tolerance values P*** to be 1 or 2 significant bits inside the p*** */
  1751. X    /* be careful to use RELATIVE error; that is, to scale the tolerance to the bbox values themselves */
  1752. X    /* now, if some user puts points way out in left field, our technique handles the ranges correctly */
  1753. X    {
  1754. X    float dx = (pxmax - pxmin) * (1.0 / (4096.0));      /* twelve binary digits out */
  1755. X    float dy = (pymax - pymin) * (1.0 / (4096.0));      /* twelve binary digits out */
  1756. X
  1757. X    Pxmin = pxmin + dx;
  1758. X    Pxmax = pxmax - dx;
  1759. X
  1760. X    Pymin = pymin + dy;
  1761. X    Pymax = pymax - dy;
  1762. X    }
  1763. X
  1764. X    /* compute inverse of external->internal sid mapping */
  1765. X    /* given an internal site number, returns user index */
  1766. X    for (sid = 0; sid < nsites; sid++)
  1767. X    inverse[sid] = GLsites[sid].vpid;
  1768. X
  1769. X    for (sid = 0; sid < nsites; sid++)    {
  1770. X    assert (sites[sid].coord.x == Usites[inverse[sid]].x);
  1771. X    assert (sites[sid].coord.y == Usites[inverse[sid]].y);
  1772. X    }
  1773. X
  1774. X    /* zero list lengths out */
  1775. X    vdinit ();
  1776. X
  1777. X    /* run the voronoi code, no triangulate */
  1778. X    triangulate = FALSE;
  1779. X    voronoi (nextone);
  1780. X
  1781. X    /* RE-copy sorted GLsites into voronoi alg sites */
  1782. X    bboxinit();
  1783. X
  1784. X    /* run the voronoi code, do triangulate */
  1785. X    triangulate = TRUE;
  1786. X    voronoi (nextone);
  1787. X
  1788. X    /* invert the integer id's in sites[], for find_dtriangles() */
  1789. X    /* and restore the original vertex values (from GLsites)     */
  1790. X    for (sid = 0; sid < nsites; sid++)    {
  1791. X        sites[sid].sitenbr = GLsites[sid].vpid;
  1792. X    sites[sid].coord.x = GLsites[sid].x;
  1793. X    sites[sid].coord.y = GLsites[sid].y;
  1794. X    }
  1795. X
  1796. X    return (0);
  1797. X}
  1798. X
  1799. Xstatic VERTTHETA vtlist[1024], slist[1024];
  1800. Xstatic int  vtnum;
  1801. X
  1802. Xstatic int
  1803. Xvtcomp (
  1804. X    VERTTHETA *vt1, VERTTHETA *vt2)
  1805. X{
  1806. X    if (vt1->theta < vt2->theta)
  1807. X    return (-1);
  1808. X    else if (vt1->theta > vt2->theta)
  1809. X    return (1);
  1810. X    else
  1811. X    return (0);
  1812. X}    
  1813. X
  1814. X/*
  1815. X    find_vregion(sid, plen, pverts)
  1816. X    given a site id 'sid' from 0..nsites-1 inclusive, 
  1817. X    returns the voronoi polygon associated with that site
  1818. X    in the array 'pverts', and its length on call stack.
  1819. X
  1820. X    the vertices are returned in counterclockwise order.
  1821. X
  1822. X    returns:
  1823. X    -1 if error condition
  1824. X    plen > 2 [i.e., the # of verts in the voronoi polygon] otherwise
  1825. X*/
  1826. Xint
  1827. Xfind_vregion (
  1828. X    int vsid,
  1829. X    float pverts[][2])
  1830. X{
  1831. Xint sid, b, k, vnum, bnd1, bnd2, bdiff, sleft, lag, lead, p1a, p1b, p2a, p2b;
  1832. Xfloat x, y, x1, y1, x2, y2, theta1, theta2, lasttheta, dtheta, h;
  1833. X
  1834. X/* note that PUTV(v,sid,vid) has the side effect of incrementing vid */
  1835. X#define PUTV(v,sid,vid)    { pverts[vid][0] = (v)->x; pverts[vid][1] = (v)->y; vid++; }
  1836. X
  1837. X#ifdef BY_CONTENTS
  1838. X    if (vsid < 0 || vsid >= nUsites) {
  1839. X    fprintf (stderr, "find_vregion(%d) called with illegal site id.\n", vsid);
  1840. X    return (-1);
  1841. X    }
  1842. X
  1843. X    /* look up user's virtual site _by contents_ */
  1844. X    x = Usites[vsid][0];
  1845. X    y = Usites[vsid][0];
  1846. X    for (sid = 0; sid < nsites; sid++)    {
  1847. X    if (GLsites[sid].x == x && GLsites[sid].y == y)
  1848. X        break;
  1849. X    }
  1850. X#endif
  1851. X
  1852. X    if (vsid < 0 || vsid >= nsites) {
  1853. X    fprintf (stderr, "find_vregion(%d) called with illegal site id.\n", vsid);
  1854. X    return (-1);
  1855. X    }
  1856. X
  1857. X    for (sid = 0; sid < nsites; sid++)    {
  1858. X    if (GLsites[sid].vpid == vsid)
  1859. X        break;
  1860. X    }
  1861. X
  1862. X    if (sid == nsites)    {
  1863. X    fprintf (stderr, "find_vregion(%d) can't find requested site at (%6.2f, %6.2f).\n", vsid, x, y);
  1864. X    return (-1);
  1865. X    }
  1866. X
  1867. X    for (k = 0; k < 4; k++)
  1868. X    corner[k]->theta = fatan2 (corner[k]->y - GLsites[sid].y, corner[k]->x - GLsites[sid].x);
  1869. X
  1870. X    for (vtnum = 0, k = 0; k < numvedges; k++)
  1871. X    if (vedges[k].nbr1 == sid || vedges[k].nbr2 == sid)   {
  1872. X        /* add both ends of the edge, and their thetas, to unsorted list (parent is edge k) */
  1873. X        slist[vtnum  ].e1 = slist[vtnum  ].e2 = k;
  1874. X        slist[vtnum  ].theta = fatan2 (vedges[k].y1 - GLsites[sid].y, vedges[k].x1 - GLsites[sid].x);
  1875. X        slist[vtnum  ].x = vedges[k].x1;
  1876. X        slist[vtnum++].y = vedges[k].y1;
  1877. X
  1878. X        slist[vtnum  ].e1 = slist[vtnum  ].e2 = k;
  1879. X            slist[vtnum  ].theta = fatan2 (vedges[k].y2 - GLsites[sid].y, vedges[k].x2 - GLsites[sid].x);
  1880. X        slist[vtnum  ].x = vedges[k].x2;
  1881. X        slist[vtnum++].y = vedges[k].y2;
  1882. X        }
  1883. X
  1884. X    /* now we have a list of vtnum thetas and vertices.  sort it on theta */
  1885. X    qsort ((char *)slist, vtnum, sizeof (VERTTHETA), vtcomp);
  1886. X
  1887. X    /* next, install the unique slist entries into vtlist */
  1888. X    lag = lead = 0;
  1889. X    vtlist[lag] = slist[lead];
  1890. X    lasttheta = -10.0;
  1891. X
  1892. X    while (lead < vtnum)    {
  1893. X        if (fabs (slist[lead].theta - lasttheta) > 1E-4) {
  1894. X        lasttheta = slist[lead].theta;
  1895. X        vtlist[lag++] = slist[lead++];
  1896. X        }
  1897. X    else    {
  1898. X        vtlist[lag-1].e2 = slist[lead++].e1;
  1899. X        }
  1900. X    }
  1901. X
  1902. X    vtnum = lag;
  1903. X/*
  1904. X    printf ("\n");
  1905. X    for (k = 0; k < vtnum; k++)
  1906. X        printf ("vtlist[%d]: x,y %f,%f; theta %f; edges %d %d\n",
  1907. X        k, vtlist[k].x, vtlist[k].y, vtlist[k].theta, vtlist[k].e1, vtlist[k].e2);
  1908. X*/
  1909. X
  1910. X    for (vnum = 0, k = 0; k < vtnum; k++)    {
  1911. X        if (fabs(vtlist[(k + vtnum - 1) % vtnum].theta - vtlist[k].theta) < 1E-4)   {
  1912. X        fprintf (stderr,"find_vregion(%d): vtlist %d, %d identical?\n", sid, (k + vtnum - 1) % vtnum, k);
  1913. X        return (-1);
  1914. X        }
  1915. X
  1916. X        x1 = vtlist[(k + vtnum - 1) % vtnum].x;
  1917. X        y1 = vtlist[(k + vtnum - 1) % vtnum].y;
  1918. X    p1a = vtlist[(k + vtnum - 1) % vtnum].e1;
  1919. X    p1b = vtlist[(k + vtnum - 1) % vtnum].e2;
  1920. X
  1921. X    x2 = vtlist[k].x;
  1922. X    y2 = vtlist[k].y;
  1923. X    p2a = vtlist[k].e1;
  1924. X    p2b = vtlist[k].e2;
  1925. X
  1926. X    /* now: if the two vertices come from the same edge, output and continue */
  1927. X    if (((p1a == p2a) || (p1a == p2b) || (p1b == p2a) || (p1b == p2b))  && (vtnum > 2))    {
  1928. X        PUTV (&vtlist[k], sid, vnum);
  1929. X        continue;
  1930. X        }
  1931. X
  1932. X    /* otherwise must fill in missing corners between x1,y1 and x2,y2 */
  1933. X    bnd1 = NBOUND(x1,y1);
  1934. X    bnd2 = NBOUND(x2,y2);
  1935. X
  1936. X    /* find number of CLOCKWISE steps around bbox */
  1937. X    if (bnd1 >= 0 && bnd2 >= 0)
  1938. X        bdiff = ((bnd2 - bnd1) + 4) % 4;    /* from 0 to 3 */
  1939. X    else
  1940. X        bdiff = 0;
  1941. X
  1942. X    /* if they were on the same bounding box edge, output and continue */
  1943. X    if (bdiff == 0) {            
  1944. X        PUTV (&vtlist[k], sid, vnum);
  1945. X        continue;
  1946. X        }
  1947. X
  1948. X    /* special case: exactly two vertices */
  1949. X    if (vtnum == 2) {
  1950. X        theta1 = vtlist[0].theta;
  1951. X        theta2 = vtlist[1].theta;
  1952. X        dtheta = theta2 - theta1;    
  1953. X
  1954. X        /* add all corners OUTSIDE the angular range of the edge as seen from the site */
  1955. X        for (b = 0; b < 4; b++)    {
  1956. X        if ((dtheta >= M_PI) && (corner[b]->theta > theta1) && (corner[b]->theta < theta2))
  1957. X            vtlist[vtnum++] = *corner[b];
  1958. X        else if ((dtheta < M_PI) && ((corner[b]->theta < theta1) || (corner[b]->theta > theta2)))
  1959. X            vtlist[vtnum++] = *corner[b];
  1960. X        }
  1961. X
  1962. X        /* resort the (small) vertex list by theta */
  1963. X        qsort ((char *)vtlist, vtnum, sizeof (VERTTHETA), vtcomp);
  1964. X
  1965. X        /* and output */
  1966. X        for (b = 0; b < vtnum; b++)
  1967. X        PUTV (&vtlist[b], sid, vnum);
  1968. X
  1969. X        break;
  1970. X        }
  1971. X
  1972. X    for (b = 0; b < bdiff; b++)
  1973. X        PUTV (corner[(bnd1 + b) % 4], sid, vnum);
  1974. X
  1975. X    PUTV (&vtlist[k], sid, vnum);
  1976. X    }    /* k 0 ..vtnum */
  1977. X
  1978. X    return (vnum);
  1979. X}
  1980. X
  1981. X/*
  1982. X    int
  1983. X    find_dtriangles (**dtris)
  1984. X
  1985. X    returns:
  1986. X    -1 if error condition, *dtris == NULL
  1987. X    o/wise, # of delaunay triangles, *dtris == array of TRIS (see voronoi.h)
  1988. X*/
  1989. Xint
  1990. Xfind_dtriangles (
  1991. X    TRI **dtris)
  1992. X{
  1993. X    if (numtris <= 0)    {
  1994. X    *dtris = NULL;
  1995. X    return (-1);
  1996. X    }
  1997. X    else    {
  1998. X    *dtris = tris;
  1999. X    return (numtris);
  2000. X    }
  2001. X}
  2002. X
  2003. X/*
  2004. X    int
  2005. X    find_dtadjacency (*(int[][2]))
  2006. X
  2007. X    returns:
  2008. X    -1 if error condition, *dtadj == NULL
  2009. X    o/wise, # of adjacency pairs, and all pairs
  2010. X    indices refer to triangle ids as returned by find_dtriangles()
  2011. X*/
  2012. Xint adjlist[MAXVERTS * 3][2];
  2013. X
  2014. Xint
  2015. Xfind_dtadjacencies (
  2016. X    int (**dtadj)[][2])        /* pointer to array of nx2 integers */
  2017. X{
  2018. Xint nadj = 0, j, k, nematched;
  2019. XTRI *trij, *trik;
  2020. X
  2021. X#define EMATCH(Ap, Aq, Bp, Bq) (Ap == Bp && Aq == Bq)
  2022. X
  2023. X    if (numtris <= 0)    {
  2024. X    *dtadj = NULL;
  2025. X    return (-1);
  2026. X    }
  2027. X    else    {
  2028. X    for (j = 0; j < numtris; j++)    {
  2029. X        trij = &tris[j];
  2030. X        nematched = 0;
  2031. X        for (k = j+1; k < numtris; k++)   {
  2032. X            trik = &tris[k];
  2033. X        if (   EMATCH(trij->v1, trij->v2, trik->v3, trik->v2)
  2034. X            || EMATCH(trij->v1, trij->v2, trik->v2, trik->v1)
  2035. X            || EMATCH(trij->v1, trij->v2, trik->v1, trik->v3)) {
  2036. X            adjlist[nadj  ][0] = j;
  2037. X            adjlist[nadj++][1] = k;
  2038. X            nematched++;
  2039. X            }
  2040. X        else if (EMATCH(trij->v2, trij->v3, trik->v3, trik->v2)
  2041. X              || EMATCH(trij->v2, trij->v3, trik->v2, trik->v1)
  2042. X              || EMATCH(trij->v2, trij->v3, trik->v1, trik->v3)) {
  2043. X            adjlist[nadj  ][0] = j;
  2044. X            adjlist[nadj++][1] = k;
  2045. X            nematched++;
  2046. X            }
  2047. X        else if (EMATCH(trij->v3, trij->v1, trik->v3, trik->v2)
  2048. X              || EMATCH(trij->v3, trij->v1, trik->v2, trik->v1)
  2049. X              || EMATCH(trij->v3, trij->v1, trik->v1, trik->v3)) {
  2050. X            adjlist[nadj  ][0] = j;
  2051. X            adjlist[nadj++][1] = k;
  2052. X            nematched++;
  2053. X            }
  2054. X    
  2055. X        if (nematched == 3)
  2056. X            break;
  2057. X        }
  2058. X        }
  2059. X    *dtadj = (int (*)[][2])adjlist;
  2060. X    return (nadj);
  2061. X    }
  2062. X}
  2063. X
  2064. X#define IEPS (2E-7)
  2065. X
  2066. Xstatic int
  2067. Xfident(float a, float b)
  2068. X{
  2069. Xfloat sum;
  2070. X
  2071. X    sum = ABS(a) + ABS(b);
  2072. X
  2073. X    if (sum == 0.0)
  2074. X    return (TRUE);
  2075. X    else    {
  2076. X    sum = (a-b) / sum;
  2077. X    return (sum > -IEPS && sum < IEPS);
  2078. X    }
  2079. X}
  2080. X
  2081. Xstatic int
  2082. Xxycollinear (
  2083. Xfloat ax, float ay, 
  2084. Xfloat bx, float by, 
  2085. Xfloat cx, float cy)
  2086. X{
  2087. Xfloat Ax, Ay, Bx, By;
  2088. X
  2089. X    Ax = bx-ax;
  2090. X    Ay = by-ay;
  2091. X
  2092. X    Bx = cx-bx;
  2093. X    By = cy-by;
  2094. X
  2095. X    return (fident (Ax * By, Bx * Ay));
  2096. X}
  2097. X
  2098. X/*
  2099. X    int
  2100. X    find_convexhull (**chverts)
  2101. X
  2102. X    returns:
  2103. X    if error condition
  2104. X         *chverts == NULL
  2105. X        returns -1 
  2106. X    o/wise, 
  2107. X        *chverts == array of named VERTs (see voronoi.h), in order around convex hull
  2108. X        *chvert[k].vpid == index of point in point set given to load_vertices()
  2109. X        returns # of convex hull vertices
  2110. X*/
  2111. Xint
  2112. Xfind_convexhull(
  2113. X    NVERT **chvertices)
  2114. X{
  2115. Xint k, nchverts, nbr1, nbr2;
  2116. XNVERT *v1, *v2, T;
  2117. Xint start, lag, lead;
  2118. X
  2119. X    if (nsites <= 2)    {
  2120. X        *chvertices = uchverts;        /* arranged correctly in load_vsites() */
  2121. X        return (nsites);
  2122. X    }
  2123. X
  2124. X    /* find first convex hull edge */
  2125. X    for (k = 0; k < nsites; k++) {
  2126. X        v1 = &chverts[k];
  2127. X
  2128. X        if (v1->onhull && v1->nbr1 != -1 && v1->nbr2 != -1)
  2129. X            break;
  2130. X        }
  2131. X
  2132. X    if (k == nsites) {
  2133. X        fprintf (stderr, "no hull edge found!\n");
  2134. X    *chvertices = NULL;
  2135. X        return (-1);
  2136. X        }
  2137. X
  2138. X    /* vpids are _internal_ indices */
  2139. X    start = lag = v1->vpid;
  2140. X    lead = v1->nbr2;
  2141. X
  2142. X    k = 0;
  2143. X    do  {
  2144. X    if (k > 0)
  2145. X        uchverts[k].nbr1 = uchverts[k-1].vpid;
  2146. X    uchverts[k].vpid = inverse[lag];
  2147. X    uchverts[k++].nbr2 = inverse[lead];
  2148. X    /* assert (lag == chverts[lead].nbr1 || lag == chverts[lead].nbr2); */
  2149. X        if (lag == chverts[lead].nbr1)  {
  2150. X            lag = lead;
  2151. X            lead = chverts[lead].nbr2;
  2152. X            }
  2153. X        else if (lag == chverts[lead].nbr2)  {
  2154. X            lag = lead;
  2155. X            lead = chverts[lead].nbr1;
  2156. X            }
  2157. X    else    {
  2158. X        fprintf (stderr, "inconsistent convex hull?\n");
  2159. X        return (0);
  2160. X        }
  2161. X        } while (lag != start);
  2162. X
  2163. X    uchverts[0].nbr1 = uchverts[k-1].vpid;
  2164. X
  2165. X#define UX(k) (Usites[uchverts[k].vpid].x)
  2166. X#define UY(k) (Usites[uchverts[k].vpid].y)
  2167. X
  2168. X    nchverts = k;
  2169. X
  2170. X#define EXCISE_CPTS
  2171. X#ifdef EXCISE_CPTS
  2172. X    /* strip out any contiguous coincident vertices */
  2173. X    /* excise degenerate vertices */
  2174. X    for (lag = k = 0; k < nchverts; k++)
  2175. X    if (!(fident(UX(k), UX((k+1) % nchverts)) && fident(UY(k), UY((k+1) % nchverts))))
  2176. X        uchverts[lag++] = uchverts[k];
  2177. X
  2178. X    if (lag != nchverts)    {
  2179. X    fprintf (stderr, "excised %d coincident convex hull vertices\n", nchverts - lag);
  2180. X    k = nchverts = lag;
  2181. X    }
  2182. X#endif
  2183. X
  2184. X#ifdef EXCISE_DEDGES
  2185. X    /* strip out any contiguous collinear vertices */
  2186. X    if (nchverts > 2)    {   /* excise degenerate edges */
  2187. X        for (lag = k = 0; k < nchverts; k++)
  2188. X      if (!xycollinear (UX(k), UY(k), UX((k+1) % nchverts), UY((k+1) % nchverts), UX((k+2) % nchverts), UY((k+2) % nchverts))) 
  2189. X        uchverts[lag++] = uchverts[k];
  2190. X
  2191. X        if (lag != nchverts)    {
  2192. X      fprintf (stderr, "excised %d degenerate convex hull edges\n", nchverts - lag);
  2193. X        k = nchverts = lag;
  2194. X      }
  2195. X    }
  2196. X#endif
  2197. X
  2198. X    /* sanity check: vertices _must_ form a list around contour, especially after excisions */
  2199. X/*
  2200. X    if (nchverts > 0)    {
  2201. X        int n, v;
  2202. X
  2203. X    for (v = n = 0; n < nchverts; n++)  {
  2204. X        v = uchverts[v].nbr2;
  2205. X        }
  2206. X    }
  2207. X*/
  2208. X
  2209. X    *chvertices = uchverts;
  2210. X    return (k);
  2211. X}
  2212. END_OF_FILE
  2213.   if test 24021 -ne `wc -c <'vregion.c'`; then
  2214.     echo shar: \"'vregion.c'\" unpacked with wrong size!
  2215.   fi
  2216.   # end of 'vregion.c'
  2217. fi
  2218. if test -f 'vregion.man' -a "${1}" != "-c" ; then 
  2219.   echo shar: Will not clobber existing file \"'vregion.man'\"
  2220. else
  2221.   echo shar: Extracting \"'vregion.man'\" \(3209 characters\)
  2222.   sed "s/^X//" >'vregion.man' <<'END_OF_FILE'
  2223. X.TH VREGION 3G
  2224. X.SH NAME
  2225. X\fBload_vsites(), find_vregions()\fP - subroutine package to compute Voronoi regions of sites in the plane
  2226. X.SH SYNOPSIS
  2227. X
  2228. X.nf
  2229. X.B #include "voronoi.h"
  2230. X
  2231. X.B int
  2232. X\fBload_vsites (n, sites, uxmin, uymin, uxmax, uymax)\fP
  2233. X.B int n;
  2234. X\fBfloat sites[][2];    /* [][0] is x, [][1] is y */\fP
  2235. X.B float uxmin, uymin, uxmax, uymax;
  2236. X
  2237. X/* load_vsites(): 
  2238. X    accept the n voronoi sites (x_k, y_k)  0 <= k < n
  2239. X    calculate and store the voronoi diagram over the n sites,
  2240. X    clipping all infinite edges to user's bounding box:
  2241. X    [uxmin <= x <= uxmax; uymin <= y <= uymax].
  2242. X    
  2243. X    note: if (uxmin,uymin,uxmax,uymax are all == 0.0), OR
  2244. X    if these do not enclose the data, load_vsites()
  2245. X    will compute a correct bounding box over the input.
  2246. X
  2247. X    returns:
  2248. X    -1 if error
  2249. X     0 otherwise
  2250. X*/
  2251. X
  2252. X.B int
  2253. X.B find_vregion (vsid, pverts)
  2254. X.B int vsid;
  2255. X.B float pverts[][2];
  2256. X
  2257. X/*
  2258. X    find_vregion(sid, plen, pverts)
  2259. X    given a site id 'sid' from 0..nsites-1 inclusive, 
  2260. X    returns the voronoi polygon associated with that site
  2261. X    in the array 'pverts', and its length on call stack.
  2262. X
  2263. X    the vertices are returned in counterclockwise order.
  2264. X
  2265. X    returns:
  2266. X    -1 if error condition
  2267. X    number of vertices in voronoi polygon, otherwise
  2268. X*/
  2269. X
  2270. X.B int
  2271. X.B find_dtriangles (dtris)
  2272. X.B TRI **dtris;
  2273. X
  2274. X/*
  2275. X    find_dtriangles (dtris)
  2276. X    returns location of list of delaunay triangles induced 
  2277. X    by n sites in *dtris, and its length on call stack.
  2278. X    see voronoi.h for a definition of the TRI struct
  2279. X
  2280. X    returns:
  2281. X    -1 if error condition
  2282. X    number of delaunay triangles, otherwise
  2283. X*/
  2284. X
  2285. X.B int
  2286. X.B find_dtriangles (dtadj)
  2287. X.B int (**dtadj)[][2])
  2288. X
  2289. X/*
  2290. X    int
  2291. X    find_dtadjacency (*(int[][2]))
  2292. X
  2293. X    returns:
  2294. X    -1 if error condition, *dtadj == NULL
  2295. X    o/wise, # of adjacency pairs, and all pairs
  2296. X    indices refer to triangle ids as returned by find_dtriangles()
  2297. X*/
  2298. X
  2299. X.B int
  2300. X.B find_convexhull(
  2301. X.B   NVERT **chvertices)
  2302. X
  2303. X/*
  2304. X    int
  2305. X    find_convexhull (**chverts)
  2306. X
  2307. X    returns:
  2308. X    if error condition
  2309. X         *chverts == NULL
  2310. X        returns -1 
  2311. X    o/wise, 
  2312. X        *chverts == array of named VERTs (see voronoi.h), in order around convex hull
  2313. X        *chvert[k].vpid == index of point in point set given to load_vertices()
  2314. X        returns # of convex hull vertices
  2315. X*/
  2316. X
  2317. X.SH DESCRIPTION
  2318. XThe \fBvregion\fP package builds on netlib code believed to be written
  2319. Xby Fortune.  The first routine, \fBload_vsites()\fP, accepts the set of
  2320. Xsites {x,y} and generates a voronoi diagram over the sites, which
  2321. Xit stores internally.  Thereafter, the data structure may be
  2322. Xqueried with \fBfind_vregion\fP which, given an integer id
  2323. Xof a site, returns the voronoi polygon induced by that site (with
  2324. Xany infinite edges suitably clipped).  Calling \fBfind_dtriangles\fP
  2325. Xreturns a list of delaunay triangles whose vertices are the 
  2326. Xsites originally loaded with \fBload_vsites()\fP.
  2327. X
  2328. X.SH USAGE
  2329. XSome usage notes: \fBload_vsites()\fP must be called each time the 
  2330. Xdata or desired bounding box changes.  The time complexity of
  2331. X\fBload_vsites()\fP is approximately \fBO(n lg n)\fP, where n is the 
  2332. Xnumber of sites.
  2333. X
  2334. X.SH FILES
  2335. X.nf
  2336. X\fB
  2337. X    voronoi.h    misc.h    vector.h    headers.h    
  2338. X    geometry.c heap.c    memory.c    edgelist.c   
  2339. X    vregion.c
  2340. X\fP
  2341. X.SH AUTHOR
  2342. XSeth Teller, from netlib code possibly authored by Fortune.
  2343. X
  2344. X
  2345. END_OF_FILE
  2346.   if test 3209 -ne `wc -c <'vregion.man'`; then
  2347.     echo shar: \"'vregion.man'\" unpacked with wrong size!
  2348.   fi
  2349.   # end of 'vregion.man'
  2350. fi
  2351. if test -f 'vrgeometry.c' -a "${1}" != "-c" ; then 
  2352.   echo shar: Will not clobber existing file \"'vrgeometry.c'\"
  2353. else
  2354.   echo shar: Extracting \"'vrgeometry.c'\" \(4006 characters\)
  2355.   sed "s/^X//" >'vrgeometry.c' <<'END_OF_FILE'
  2356. X#include <math.h>
  2357. X#include "vordefs.h"
  2358. X
  2359. Xgeominit()
  2360. X{
  2361. X    struct Edge e;
  2362. X    float sn;
  2363. X
  2364. X    freeinit (&efl, sizeof (struct Edge));
  2365. X    nvertices = 0;
  2366. X    nedges = 0;
  2367. X    sn = nsites + 4;
  2368. X    sqrt_nsites = sqrt(sn);
  2369. X    vdeltay = vymax - vymin;
  2370. X    vdeltax = vxmax - vxmin;
  2371. X    siteidx = 0;
  2372. X}
  2373. X
  2374. Xstruct Edge *bisect(s1,s2)
  2375. Xstruct    Site *s1,*s2;
  2376. X{
  2377. X    float dx,dy,adx,ady;
  2378. X    struct Edge *newedge;
  2379. X
  2380. X    newedge = (struct Edge *) getfree(&efl);
  2381. X
  2382. X    newedge->reg[0] = s1;
  2383. X    newedge->reg[1] = s2;
  2384. X    ref(s1); 
  2385. X    ref(s2);
  2386. X    newedge->ep[0] = (struct Site *) NULL;
  2387. X    newedge->ep[1] = (struct Site *) NULL;
  2388. X
  2389. X    dx = s2->coord.x - s1->coord.x;
  2390. X    dy = s2->coord.y - s1->coord.y;
  2391. X    adx = dx>0 ? dx : -dx;
  2392. X    ady = dy>0 ? dy : -dy;
  2393. X    newedge->c = s1->coord.x * dx + s1->coord.y * dy + (dx*dx + dy*dy)*0.5;
  2394. X    if (adx>ady) {    
  2395. X    newedge->a = 1.0; 
  2396. X    newedge->b = dy/dx; 
  2397. X    newedge->c /= dx;
  2398. X    } else {    
  2399. X    newedge->b = 1.0; 
  2400. X    newedge->a = dx/dy; 
  2401. X    newedge->c /= dy;
  2402. X    }
  2403. X    newedge->edgenbr = nedges;
  2404. X    out_bisector(newedge);
  2405. X    nedges += 1;
  2406. X    return(newedge);
  2407. X}
  2408. X
  2409. Xstruct Site *sintersect(el1, el2, p)
  2410. Xstruct Halfedge *el1, *el2;
  2411. Xstruct Point *p;
  2412. X{
  2413. X    struct Edge *e1,*e2, *e;
  2414. X    struct Halfedge *el;
  2415. X    float d, xint, yint;
  2416. X    int right_of_site;
  2417. X    struct Site *v;
  2418. X
  2419. X    e1 = el1->ELedge;
  2420. X    e2 = el2->ELedge;
  2421. X    if (e1 == (struct Edge*)NULL || e2 == (struct Edge*)NULL) 
  2422. X    return ((struct Site *) NULL);
  2423. X    if (e1->reg[1] == e2->reg[1]) 
  2424. X    return ((struct Site *) NULL);
  2425. X    d = e1->a * e2->b - e1->b * e2->a;
  2426. X    if (-1.0e-10<d && d<1.0e-10) 
  2427. X    return ((struct Site *) NULL);
  2428. X    xint = (e1->c*e2->b - e2->c*e1->b)/d;
  2429. X    yint = (e2->c*e1->a - e1->c*e2->a)/d;
  2430. X    if ((e1->reg[1]->coord.y < e2->reg[1]->coord.y) ||
  2431. X        (e1->reg[1]->coord.y == e2->reg[1]->coord.y &&
  2432. X        e1->reg[1]->coord.x < e2->reg[1]->coord.x) ) {    
  2433. X    el = el1; 
  2434. X    e = e1;
  2435. X    } else {    
  2436. X    el = el2; 
  2437. X    e = e2;
  2438. X    }
  2439. X    right_of_site = xint >= e->reg[1]->coord.x;
  2440. X    if ((right_of_site && el->ELpm == le) ||
  2441. X       (!right_of_site && el->ELpm == re)) 
  2442. X    return ((struct Site *) NULL);
  2443. X    v = (struct Site *) getfree(&sfl);
  2444. X    v->refcnt = 0;
  2445. X    v->coord.x = xint;
  2446. X    v->coord.y = yint;
  2447. X    return(v);
  2448. X}
  2449. X
  2450. X/* returns 1 if p is to right of halfedge e */
  2451. Xint right_of(el, p)
  2452. Xstruct Halfedge *el;
  2453. Xstruct Point *p;
  2454. X{
  2455. X    struct Edge *e;
  2456. X    struct Site *topsite;
  2457. X    int right_of_site, above, fast;
  2458. X    float dxp, dyp, dxs, t1, t2, t3, yl;
  2459. X
  2460. X    e = el->ELedge;
  2461. X    topsite = e->reg[1];
  2462. X    right_of_site = p->x > topsite->coord.x;
  2463. X    if (right_of_site && el->ELpm == le) 
  2464. X    return(1);
  2465. X    if (!right_of_site && el->ELpm == re) 
  2466. X    return (0);
  2467. X    if (e->a == 1.0) {    
  2468. X    dyp = p->y - topsite->coord.y;
  2469. X    dxp = p->x - topsite->coord.x;
  2470. X    fast = 0;
  2471. X    if ((!right_of_site && e->b<0.0) || (right_of_site && e->b>=0.0) ) {    
  2472. X        above = dyp>= e->b*dxp;    
  2473. X        fast = above;
  2474. X    } else {    
  2475. X        above = p->x + p->y*e->b > e->c;
  2476. X        if (e->b<0.0) 
  2477. X        above = !above;
  2478. X        if (!above) 
  2479. X        fast = 1;
  2480. X    }
  2481. X    if (!fast) {    
  2482. X        dxs = topsite->coord.x - (e->reg[0])->coord.x;
  2483. X        above = e->b * (dxp*dxp - dyp*dyp) <
  2484. X                    dxs*dyp*(1.0+2.0*dxp/dxs + e->b*e->b);
  2485. X        if (e->b<0.0) 
  2486. X        above = !above;
  2487. X    }
  2488. X    } else {    /*e->b==1.0 */
  2489. X    yl = e->c - e->a*p->x;
  2490. X    t1 = p->y - yl;
  2491. X    t2 = p->x - topsite->coord.x;
  2492. X    t3 = yl - topsite->coord.y;
  2493. X    above = t1*t1 > t2*t2 + t3*t3;
  2494. X    }
  2495. X    return (el->ELpm==le ? above : !above);
  2496. X}
  2497. X
  2498. Xvoid
  2499. Xv_endpoint(e, lr, s)
  2500. Xstruct Edge *e;
  2501. Xint    lr;
  2502. Xstruct Site *s;
  2503. X{
  2504. X    e->ep[lr] = s;
  2505. X    ref(s);
  2506. X    if (e->ep[re-lr]==(struct Site *)NULL) 
  2507. X    return;
  2508. X    out_ep(e);
  2509. X    deref(e->reg[le]);
  2510. X    deref(e->reg[re]);
  2511. X    makefree(e, &efl);
  2512. X}
  2513. X
  2514. Xfloat dist(s,t)
  2515. Xstruct Site *s,*t;
  2516. X{
  2517. X    float dx,dy;
  2518. X    dx = s->coord.x - t->coord.x;
  2519. X    dy = s->coord.y - t->coord.y;
  2520. X    return(sqrt(dx*dx + dy*dy));
  2521. X}
  2522. X
  2523. X
  2524. Xint makevertex(v)
  2525. Xstruct Site *v;
  2526. X{
  2527. X    v->sitenbr = nvertices;
  2528. X    nvertices += 1;
  2529. X    out_vertex(v);
  2530. X}
  2531. X
  2532. X
  2533. Xderef(v)
  2534. Xstruct    Site *v;
  2535. X{
  2536. X    v->refcnt -= 1;
  2537. X    if (v->refcnt == 0) 
  2538. X    makefree(v, &sfl);
  2539. X}
  2540. X
  2541. Xref(v)
  2542. Xstruct Site *v;
  2543. X{
  2544. X    v->refcnt += 1;
  2545. X}
  2546. END_OF_FILE
  2547.   if test 4006 -ne `wc -c <'vrgeometry.c'`; then
  2548.     echo shar: \"'vrgeometry.c'\" unpacked with wrong size!
  2549.   fi
  2550.   # end of 'vrgeometry.c'
  2551. fi
  2552. echo shar: End of archive 1 \(of 1\).
  2553. cp /dev/null ark1isdone
  2554. MISSING=""
  2555. for I in 1 ; do
  2556.     if test ! -f ark${I}isdone ; then
  2557.     MISSING="${MISSING} ${I}"
  2558.     fi
  2559. done
  2560. if test "${MISSING}" = "" ; then
  2561.     echo You have the archive.
  2562.     rm -f ark[1-9]isdone
  2563. else
  2564.     echo You still must unpack the following archives:
  2565.     echo "        " ${MISSING}
  2566. fi
  2567. exit 0
  2568. exit 0 # Just in case...
  2569.