1 /* qhull.c - For the Gambit Project
2 
3    This file contains the implementation code taken from qhull and
4 incorporated into the Gambit source code.  We have placed all qhull
5 code in qhull.h and qhull.c to avoid adding to the number of files
6 in Gambit, and, more importantly, to express the idea that, from our
7 point of view, this is a blackbox.  We are unlikely to be able to
8 answer questions concerning this code, and those who wish to modify
9 it should consider beginning with the version distributed by the
10 Geometry Center.
11 */
12 
13 #include "pelqhull.h"
14 
15 /*************************************************************************/
16 /******************* implementation code from mem.c **********************/
17 /*************************************************************************/
18 
19 /* mem.c - memory management routines for qhull
20 
21    This is a standalone program.
22 
23    To initialize memory:
24 
25      qh_meminit (stderr);  /
26     qh_meminitbuffers (qh IStracing, qh_MEMalign, 7, qh_MEMbufsize,qh_MEMinitbuf);
27     qh_memsize(sizeof(facetT));
28     qh_memsize(sizeof(facetT));
29     ...
30     qh_memsetup();
31 
32    To free up all memory buffers:
33     qh_memfreeshort (&curlong, &totlong);
34 
35 
36    uses Quickfit algorithm (freelists for commonly allocated sizes)
37    assumes small sizes for freelists (it discards the tail of memory buffers)
38 
39    see README and mem.h
40    see global.c (qh_initbuffers) for an example of using mem.c
41 
42    copyright (c) 1993-1994 The Geometry Center
43 */
44 
45 /* ============ -global data structure ==============
46     see mem.h for definition
47 */
48 
49 qhmemT qhmem= {0};     /* remove "= {0}" if this causes a compiler error */
50 
51 /* internal functions */
52 
53 static int qh_intcompare(const void *i, const void *j);
54 
55 /*========== functions in alphabetical order ======== */
56 
57 /*-------------------------------------------------
58 -intcompare- used by qsort and bsearch to compare two integers
59 */
qh_intcompare(const void * i,const void * j)60 static int qh_intcompare(const void *i, const void *j) {
61   return(*((int *)i) - *((int *)j));
62 } /* intcompare */
63 
64 
65 /*-------------------------------------------------
66 -memalloc- allocates memory for object from qhmem
67 returns:
68  pointer to allocated memory (errors if insufficient memory)
69  outsize= actual size allocated, may be NULL
70 notes:
71   use qh_memalloc_() for inline code for quick allocations
72 */
qh_memalloc(int insize)73 void *qh_memalloc(int insize) {
74   void **freelistp, *newbuffer;
75   int index, size;
76   int outsize, bufsize;
77   void *object;
78 
79   if ((unsigned) insize <= (unsigned) qhmem.LASTsize) {
80     index= qhmem.indextable[insize];
81     freelistp= qhmem.freelists+index;
82     if ((object= *freelistp)) {
83       qhmem.cntquick++;
84       *freelistp= *((void **)*freelistp);  /* replace freelist with next object */
85       return (object);
86     }else {
87       outsize= qhmem.sizetable[index];
88       qhmem.cntshort++;
89       if (outsize > qhmem .freesize) {
90 	if (!qhmem.curbuffer)
91 	  bufsize= qhmem.BUFinit;
92         else
93 	  bufsize= qhmem.BUFsize;
94         qhmem.totshort += bufsize;
95 
96 	if (!(newbuffer= malloc(bufsize))) qhull_fatal(1);
97 
98 	*((void **)newbuffer)= qhmem.curbuffer;  /* prepend newbuffer to curbuffer
99 						    list */
100 	qhmem.curbuffer= newbuffer;
101         size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
102 	qhmem.freemem= (void *)((char *)newbuffer+size);
103 	qhmem.freesize= bufsize - size;
104       }
105       object= qhmem.freemem;
106       qhmem.freemem= (void *)((char *)qhmem.freemem + outsize);
107       qhmem.freesize -= outsize;
108       return object;
109     }
110   }else {                     /* long allocation */
111 
112     if (!qhmem.indextable) qhull_fatal(2);
113 
114     outsize= insize;
115     qhmem .cntlong++;
116     qhmem .curlong++;
117     qhmem .totlong += outsize;
118     if (qhmem.maxlong < qhmem.totlong)
119       qhmem.maxlong= qhmem.totlong;
120 
121     if (!(object= malloc(outsize))) qhull_fatal(3);
122 
123     if (qhmem.IStracing >= 5)
124       fprintf (qhmem.ferr, "qh_memalloc long: %d bytes at %p\n", outsize, object);
125   }
126   return (object);
127 } /* memalloc */
128 
129 
130 /*-------------------------------------------------
131 -memfree- frees memory object (may be NULL)
132   size is either insize or outsize from qh_memalloc
133   type checking warns if using (void **)object
134   qh_memfree_()- in-line code for quick free's
135 */
qh_memfree(void * object,int size)136 void qh_memfree(void *object, int size) {
137   void **freelistp;
138 
139   if (!object)
140     return;
141   if (size <= qhmem.LASTsize) {
142     qhmem .freeshort++;
143     freelistp= qhmem.freelists + qhmem.indextable[size];
144     *((void **)object)= *freelistp;
145     *freelistp= object;
146   }else {
147     qhmem .freelong++;
148     qhmem .totlong -= size;
149     free (object);
150     if (qhmem.IStracing >= 5)
151       fprintf (qhmem.ferr, "qh_memfree long: %d bytes at %p\n", size, object);
152   }
153 } /* memfree */
154 
155 
156 /*-------------------------------------------------
157 -memfreeshort- frees up all short and qhmem memory allocations
158 returns: number and size of current long allocations
159 */
qh_memfreeshort(int * curlong,int * totlong)160 void qh_memfreeshort (int *curlong, int *totlong) {
161   void *buffer, *nextbuffer;
162 
163   *curlong= qhmem .cntlong - qhmem .freelong;
164   *totlong= qhmem .totlong;
165   for(buffer= qhmem.curbuffer; buffer; buffer= nextbuffer) {
166     nextbuffer= *((void **) buffer);
167     free(buffer);
168   }
169   qhmem.curbuffer= NULL;
170   if (qhmem .LASTsize) {
171     free (qhmem .indextable);
172     free (qhmem .freelists);
173     free (qhmem .sizetable);
174   }
175   memset((char *)&qhmem, 0, sizeof qhmem);  /* every field is 0, FALSE, NULL */
176 } /* memfreeshort */
177 
178 
179 /*-------------------------------------------------
180 -meminit- initialize memory (memalloc errors until memsetup)
181 */
qh_meminit(FILE * ferr)182 void qh_meminit (FILE *ferr) {
183 
184   memset((char *)&qhmem, 0, sizeof qhmem);  /* every field is 0, FALSE, NULL */
185   qhmem.ferr= ferr;
186 
187 #ifndef __BCC55__
188   // This condition is always false under BCC55
189   if (sizeof(void*) < sizeof(int)) qhull_fatal(4);
190 #endif  // __BCC55__
191 } /* meminit */
192 
193 /*-------------------------------------------------
194 -meminitbuffers- initialize memory buffers
195 */
qh_meminitbuffers(int tracelevel,int alignment,int numsizes,int bufsize,int bufinit)196 void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
197 
198   qhmem.IStracing= tracelevel;
199   qhmem.NUMsizes= numsizes;
200   qhmem.BUFsize= bufsize;
201   qhmem.BUFinit= bufinit;
202   qhmem.ALIGNmask= alignment-1;
203 
204   if (qhmem.ALIGNmask & ~qhmem.ALIGNmask) qhull_fatal(5);
205 
206   qhmem.sizetable= (int *) calloc (numsizes, sizeof(int));
207   qhmem.freelists= (void **) calloc (numsizes, sizeof(void *));
208 
209   if (!qhmem.sizetable || !qhmem.freelists) qhull_fatal(6);
210 
211   if (qhmem.IStracing >= 1)
212     fprintf (qhmem.ferr, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
213 } /* meminitbuffers */
214 
215 /*-------------------------------------------------
216 -memsetup- set up memory after running memsize()
217 */
qh_memsetup(void)218 void qh_memsetup (void) {
219   int k,i;
220 
221   qsort(qhmem.sizetable, qhmem.TABLEsize, sizeof(int), qh_intcompare);
222   qhmem.LASTsize= qhmem.sizetable[qhmem.TABLEsize-1];
223 
224   if (qhmem .LASTsize >= qhmem .BUFsize || qhmem.LASTsize >= qhmem .BUFinit)
225     qhull_fatal(7);
226 
227   if (!(qhmem.indextable= (int *)malloc((qhmem.LASTsize+1) * sizeof(int))))
228     qhull_fatal(8);
229 
230   for(k=qhmem.LASTsize+1; k--; )
231     qhmem.indextable[k]= k;
232   i= 0;
233   for(k= 0; k <= qhmem.LASTsize; k++) {
234     if (qhmem.indextable[k] <= qhmem.sizetable[i])
235       qhmem.indextable[k]= i;
236     else
237       qhmem.indextable[k]= ++i;
238   }
239 } /* memsetup */
240 
241 /*-------------------------------------------------
242 -memsize- define a free list for this size
243 */
qh_memsize(int size)244 void qh_memsize(int size) {
245   int k;
246 
247   if (qhmem .LASTsize) qhull_fatal(9);
248 
249   size= (size + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
250   for(k= qhmem.TABLEsize; k--; ) {
251     if (qhmem.sizetable[k] == size)
252       return;
253   }
254   if (qhmem.TABLEsize < qhmem.NUMsizes)
255     qhmem.sizetable[qhmem.TABLEsize++]= size;
256   else
257     fprintf(qhmem.ferr, "qhull warning (memsize): free list table has room for only %d sizes\n", qhmem.NUMsizes);
258 } /* memsize */
259 
260 
261 /*-------------------------------------------------
262 -memstatistics-  print out memory statistics
263 */
qh_memstatistics(FILE * fp)264 void qh_memstatistics (FILE *fp) {
265   int i, count;
266   void *object;
267 
268   fprintf (fp, "\nmemory statistics:\n\
269 %7d quick allocations\n\
270 %7d short allocations\n\
271 %7d long allocations\n\
272 %7d short frees\n\
273 %7d long frees\n\
274 %7d bytes of short memory in use or on freelists\n\
275 %7d bytes of long memory allocated (except for input)\n\
276 %7d bytes of long memory in use (in %d pieces)\n\
277 %7d bytes per memory buffer (initially %d bytes)\n",
278 	   qhmem .cntquick, qhmem.cntshort, qhmem.cntlong,
279 	   qhmem .freeshort, qhmem.freelong,
280 	   qhmem .totshort - qhmem .freesize,
281 	   qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong,
282 	   qhmem .BUFsize, qhmem .BUFinit);
283   if (qhmem.cntlarger) {
284     fprintf (fp, "%7d calls to qh_setlarger\n%7.2g     average copy size\n",
285 	   qhmem.cntlarger, ((float) qhmem.totlarger)/ qhmem.cntlarger);
286     fprintf (fp, "  freelists (bytes->count):");
287   }
288   for (i=0; i<qhmem.TABLEsize; i++) {
289     count=0;
290     for (object= qhmem .freelists[i]; object; object= *((void **)object))
291       count++;
292     fprintf (fp, " %d->%d", qhmem.sizetable[i], count);
293   }
294   fprintf (fp, "\n\n");
295 } /* memstatistics */
296 
297 
298 /*************************************************************************/
299 /******************* implementation code from set.c **********************/
300 /*************************************************************************/
301 
302 /* set.c -- implements set manipulations needed for quickhull
303 
304    see README and set.h
305 
306    copyright (c) 1993-1994 The Geometry Center
307 */
308 
309 /*----------- internal macros -------------------
310 -SETsizeaddr_(set) - return pointer to actual size+1 of set (set CANNOT be NULL!!)
311     *SETsizeaddr==NULL or e[*SETsizeaddr-1]==NULL
312 */
313 #define SETsizeaddr_(set) ((int *)(&((set)->e[(set)->maxsize])))
314 
315 /*============ functions in alphabetical order ===================*/
316 
317 /*----------------------------------------
318 -setaddnth- adds newelem as n'th element of sorted or unsorted set
319   setp and newelem must be defined
320   set may be a temp set
321   nth=0 is first element
322   errors if nth is out of bounds
323 */
qh_setaddnth(setT ** setp,int nth,void * newelem)324 void qh_setaddnth(setT **setp, int nth, void *newelem) {
325   int *sizep, oldsize, i;
326   void **oldp, **newp;
327 
328   if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
329     qh_setlarger(setp);
330     sizep= SETsizeaddr_(*setp);
331   }
332   oldsize= *sizep - 1;
333   if (nth < 0 || nth > oldsize) qhull_fatal(10);
334 
335   (*sizep)++;
336   oldp= SETelemaddr_(*setp, oldsize, void);   /* NULL */
337   newp= oldp+1;
338   for (i= oldsize-nth+1; i--; )  /* move at least NULL  */
339     *(newp--)= *(oldp--);       /* may overwrite *sizep */
340   *newp= newelem;
341 } /* setaddnth */
342 
343 
344 /*----------------------------------------
345 -setaddsorted- adds an element to a sorted set
346   setp and newelem must be defined
347   set may be a temp set
348   nop if newelem already in set
349 */
qh_setaddsorted(setT ** setp,void * newelem)350 void qh_setaddsorted(setT **setp, void *newelem) {
351   int newindex=0;
352   void *elem, **elemp;
353 
354   FOREACHelem_(*setp) {          /* could use binary search instead */
355     if (elem < newelem)
356       newindex++;
357     else if (elem == newelem)
358       return;
359     else
360       break;
361   }
362   qh_setaddnth(setp, newindex, newelem);
363 } /* setaddsorted */
364 
365 
366 /*----------------------------------------
367 -setappend- appends an element to a set
368   set may be a temp set
369   *setp and newelem may be NULL
370 */
qh_setappend(setT ** setp,void * newelem)371 void qh_setappend(setT **setp, void *newelem) {
372   int *sizep;
373   void **endp;
374 
375   if (!newelem)
376     return;
377   if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
378     qh_setlarger(setp);
379     sizep= SETsizeaddr_(*setp);
380   }
381   *(endp= &((*setp)->e[(*sizep)++ - 1]))= newelem;
382   *(++endp)= NULL;
383 } /* setappend */
384 
385 /*----------------------------------------
386 -setappend_set- appends a set to a set
387   *setp and set may be NULL
388   setp can not be a temp set
389 */
qh_setappend_set(setT ** setp,setT * setA)390 void qh_setappend_set(setT **setp, setT *setA) {
391   int *sizep, sizeA, size;
392   setT *oldset;
393 
394   if (!setA)
395     return;
396   SETreturnsize_(setA, sizeA);
397   if (!*setp)
398     *setp= qh_setnew (sizeA);
399   sizep= SETsizeaddr_(*setp);
400   if (!(size= *sizep))
401     size= (*setp)->maxsize;
402   else
403     size--;
404   if (size + sizeA >(int) (*setp)->maxsize) {
405     oldset= *setp;
406     *setp= qh_setcopy (oldset, sizeA);
407     qh_setfree (&oldset);
408     sizep= SETsizeaddr_(*setp);
409   }
410   *sizep= size+sizeA+1;   /* memcpy may overwrite */
411   if (sizeA > 0)
412     memcpy((char *)&((*setp)->e[size]), (char *)&(setA->e[0]), SETelemsize *(sizeA+1));
413 } /* setappend_set */
414 
415 
416 /*----------------------------------------
417 -setappend2ndlast- makes newelem the next to the last element in set
418   set must have at least one element, newelem must be defined
419   set may be a temp set
420 */
qh_setappend2ndlast(setT ** setp,void * newelem)421 void qh_setappend2ndlast(setT **setp, void *newelem) {
422   int *sizep;
423   void **endp, **lastp;
424 
425   if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
426     qh_setlarger(setp);
427     sizep= SETsizeaddr_(*setp);
428   }
429   endp= SETelemaddr_(*setp, (*sizep)++ -1, void); /* NULL */
430   lastp= endp-1;
431   *(endp++)= *lastp;
432   *endp= NULL;    /* may overwrite *sizep */
433   *lastp= newelem;
434 } /* setappend2ndlast */
435 
436 
437 /*----------------------------------------
438 -setcheck- check set for validity
439 */
qh_setcheck(setT * set,const char * typenameNEW,int id)440 void qh_setcheck(setT *set, const char *typenameNEW, int id) {
441   int maxsize, size;
442   int waserr= 0;
443 
444   if (!set)
445     return;
446   SETreturnsize_(set, size);
447   maxsize= set->maxsize;
448   if (size > maxsize || !maxsize) {
449     fprintf (qhmem.ferr, "qhull internal error (setcheck): actual size %d of %s%d is greater than max size %d\n",
450 	     size, typenameNEW, id, maxsize);
451     waserr= 1;
452   }else if (set->e[size]) {
453     fprintf (qhmem.ferr, "qhull internal error (setcheck): %s%d (size %d max %d) is not null terminated.\n",
454 	     typenameNEW, id, maxsize, size-1);
455     waserr= 1;
456   }
457   if (waserr) qhull_fatal(11);
458 
459 } /* setcheck */
460 
461 
462 /*----------------------------------------
463 -setcopy- copies a sorted or unsorted set into another
464 returns:
465   new set is actual size of old set plus extra
466 */
qh_setcopy(setT * set,int extra)467 setT *qh_setcopy(setT *set, int extra) {
468   setT *newset;
469   int size;
470 
471   if (extra < 0)
472     extra= 0;
473   SETreturnsize_(set, size);
474   newset= qh_setnew(size+extra);
475   *SETsizeaddr_(newset)= size+1;    /* memcpy may overwrite */
476   memcpy((char *)&(newset->e[0]), (char *)&(set->e[0]), SETelemsize *(size+1));
477   return (newset);
478 } /* setcopy */
479 
480 
481 /*----------------------------------------
482 -setdel- deletes oldelem from unsorted set.
483    if found, overwrites newlelem with lastelem
484    set may be NULL, oldelem must not be NULL;
485 returns:
486   returns oldelem if it was deleted
487 */
qh_setdel(setT * set,void * oldelem)488 void *qh_setdel(setT *set, void *oldelem) {
489   void **elemp, **lastp;
490   int *sizep;
491 
492   if (!set)
493     return NULL;
494   elemp= SETaddr_(set, void);
495   while (*elemp != oldelem && *elemp)
496     elemp++;
497   if (*elemp) {
498     sizep= SETsizeaddr_(set);
499     if (!(*sizep)--)         /*  if was a full set */
500       *sizep= set->maxsize;  /*     *sizep= (maxsize-1)+ 1 */
501     lastp= SETelemaddr_(set, *sizep-1, void);
502     *elemp= *lastp;      /* may overwrite itself */
503     *lastp= NULL;
504     return oldelem;
505   }
506   return NULL;
507 } /* setdel */
508 
509 
510 /*----------------------------------------
511 -setdellast- return last element of set or NULL
512    delete element from set
513    set may be NULL
514 */
qh_setdellast(setT * set)515 void *qh_setdellast(setT *set) {
516   int setsize;
517   void **last;
518   void *returnvalue;
519 
520   if (!set || !(set->e[0]))
521     return NULL;
522   if ((setsize= (long)*(last= &(set->e[set->maxsize])))) {
523     returnvalue= set->e[setsize - 2];
524     set->e[setsize - 2]= NULL;
525     *last= (void *)((long)*last - 1);
526   }else {
527     returnvalue= set->e[set->maxsize - 1];
528     set->e[set->maxsize - 1]= NULL;
529     // This (void *) cast was in the original, 1990s, pre-64-bit Pelican
530     *last= reinterpret_cast<void *>(set->maxsize);
531   }
532   return returnvalue;
533 } /* setdellast */
534 
535 
536 /*----------------------------------------
537 -setdelnth- deletes nth element from unsorted set
538   errors if nth invalid
539   returns the element
540 */
qh_setdelnth(setT * set,int nth)541 void *qh_setdelnth(setT *set, int nth) {
542   void **elemp, **lastp, *elem;
543   int *sizep;
544 
545 
546   elemp= SETelemaddr_(set, nth, void);
547   sizep= SETsizeaddr_(set);
548   if (!(*sizep)--)         /*  if was a full set */
549     *sizep= set->maxsize;  /*     *sizep= (maxsize-1)+ 1 */
550 
551   if (nth < 0 || nth >= *sizep) qhull_fatal(12);
552 
553   lastp= SETelemaddr_(set, *sizep-1, void);
554   elem= *elemp;
555   *elemp= *lastp;      /* may overwrite itself */
556   *lastp= NULL;
557   return elem;
558 } /* setdelnth */
559 
560 /*----------------------------------------
561 -setdelnthsorted- deletes nth element from sorted set
562   sort order is undefined
563   errors if nth invalid
564   see also: setnew_delnthsorted
565 */
qh_setdelnthsorted(setT * set,int nth)566 void *qh_setdelnthsorted(setT *set, int nth) {
567   void **newp, **oldp, *elem;
568   int *sizep;
569 
570   sizep= SETsizeaddr_(set);
571 
572   if ( nth < 0 ||
573       (*sizep && nth >= *sizep-1) ||
574       nth >= (int)set->maxsize )
575     qhull_fatal(13);
576 
577   newp= SETelemaddr_(set, nth, void);
578   elem= *newp;
579   oldp= newp+1;
580   while ((*(newp++)= *(oldp++)))
581     ; /* copy remaining elements and NULL */
582   if (!(*sizep)--)         /*  if was a full set */
583     *sizep= set->maxsize;  /*     *sizep= (max size-1)+ 1 */
584   return elem;
585 } /* setdelnthsorted */
586 
587 
588 /*----------------------------------------
589 -setdelsorted- deletes oldelem from sorted set
590   sort order is undefined
591   set may be NULL
592   returns oldelem if it was deleted
593 */
qh_setdelsorted(setT * set,void * oldelem)594 void *qh_setdelsorted(setT *set, void *oldelem) {
595   void **newp, **oldp;
596   int *sizep;
597 
598   if (!set)
599     return NULL;
600   newp= SETaddr_(set, void);
601   while(*newp != oldelem && *newp)
602     newp++;
603   if (*newp) {
604     oldp= newp+1;
605     while ((*(newp++)= *(oldp++)))
606       ; /* copy remaining elements */
607     sizep= SETsizeaddr_(set);
608     if (!(*sizep)--)    /*  if was a full set */
609       *sizep= set->maxsize;  /*     *sizep= (max size-1)+ 1 */
610     return oldelem;
611   }
612   return NULL;
613 } /* setdelsorted */
614 
615 
616 /*----------------------------------------
617 -setequal- returns 1 if two sorted sets are equal, otherwise returns 0
618     either set may be NULL
619 */
qh_setequal(setT * setA,setT * setB)620 int qh_setequal(setT *setA, setT *setB) {
621   void **elemAp, **elemBp;
622   int sizeA, sizeB;
623 
624   SETreturnsize_(setA, sizeA);
625   SETreturnsize_(setB, sizeB);
626   if (sizeA != sizeB)
627     return 0;
628   if (!sizeA)
629     return 1;
630   elemAp= SETaddr_(setA, void);
631   elemBp= SETaddr_(setB, void);
632   if (!memcmp((char *)elemAp, (char *)elemBp, sizeA*SETelemsize))
633     return 1;
634   return 0;
635 } /* setequal */
636 
637 
638 /*----------------------------------------
639 -setequal_except- returns 1 if two sorted sets are equal except for 2 elements
640   neither set may be NULL
641   false if either skip is missing
642   if second skip is NULL,
643      can skip any one element
644 */
qh_setequal_except(setT * setA,void * skipelemA,setT * setB,void * skipelemB)645 int qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB) {
646   void **elemA, **elemB;
647   int skip=0;
648 
649   elemA= SETaddr_(setA, void);
650   elemB= SETaddr_(setB, void);
651   while (1) {
652     if (*elemA == skipelemA) {
653       skip++;
654       elemA++;
655     }
656     if (skipelemB) {
657       if (*elemB == skipelemB) {
658         skip++;
659         elemB++;
660       }
661     }else if (*elemA != *elemB) {
662       skip++;
663       if (!(skipelemB= *elemB++))
664         return 0;
665     }
666     if (!*elemA)
667       break;
668     if (*elemA++ != *elemB++)
669       return 0;
670   }
671   if (skip != 2 || *elemB)
672     return 0;
673   return 1;
674 } /* setequal_except */
675 
676 
677 /*----------------------------------------
678 -setequal_skip- returns 1 if two sorted sets are equal except for skips
679   neither set may be NULL
680   false if different size
681 */
qh_setequal_skip(setT * setA,int skipA,setT * setB,int skipB)682 int qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB) {
683   void **elemA, **elemB, **skipAp, **skipBp;
684 
685   elemA= SETaddr_(setA, void);
686   elemB= SETaddr_(setB, void);
687   skipAp= SETelemaddr_(setA, skipA, void);
688   skipBp= SETelemaddr_(setB, skipB, void);
689   while (1) {
690     if (elemA == skipAp)
691       elemA++;
692     if (elemB == skipBp)
693       elemB++;
694     if (!*elemA)
695       break;
696     if (*elemA++ != *elemB++)
697       return 0;
698   }
699   if (*elemB)
700     return 0;
701   return 1;
702 } /* setequal_skip */
703 
704 
705 /*----------------------------------------
706 -setfree- frees the space occupied by a sorted or unsorted set
707   set may be NULL
708 */
qh_setfree(setT ** setp)709 void qh_setfree(setT **setp) {
710   int size;
711   void **freelistp;
712 
713   if (*setp) {
714     size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize;
715     if (size <= qhmem.LASTsize) {
716       qh_memfree_(*setp, size, freelistp);
717     }else
718       qh_memfree (*setp, size);
719     *setp= NULL;
720   }
721 } /* setfree */
722 
723 
724 /*----------------------------------------
725 -setfreelong- frees a set only if it's in long memory
726   set may be NULL
727 */
qh_setfreelong(setT ** setp)728 void qh_setfreelong(setT **setp) {
729   int size;
730 
731   if (*setp) {
732     size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize;
733     if (size > qhmem.LASTsize) {
734       qh_memfree (*setp, size);
735       *setp= NULL;
736     }
737   }
738 } /* setfreelong */
739 
740 
741 /*----------------------------------------
742 -setin- returns 1 if setelem is in a set, 0 otherwise
743   set may be NULL or unsorted
744 */
qh_setin(setT * set,void * setelem)745 int qh_setin(setT *set, void *setelem) {
746   void *elem, **elemp;
747 
748   FOREACHelem_(set) {
749     if (elem == setelem)
750       return 1;
751   }
752   return 0;
753 } /* setin */
754 
755 
756 /*----------------------------------------
757 -setindex- returns the index of elem in set.   If none, returns -1
758   set may be NULL and may contain nulls.
759 */
qh_setindex(setT * set,void * atelem)760 int qh_setindex(setT *set, void *atelem) {
761   void **elem;
762   int size, i;
763 
764   SETreturnsize_(set, size);
765   if (size > (int)set->maxsize)
766     return -1;
767   elem= SETaddr_(set, void);
768   for (i=0; i<size; i++) {
769     if (*elem++ == atelem)
770       return i;
771   }
772   return -1;
773 } /* setindex */
774 
775 
776 /*----------------------------------------
777 -setlarger- returns a larger set that contains elements of *setp
778   the set is at least twice as large
779   updates qhmem.tempstack if needed
780 */
qh_setlarger(setT ** oldsetp)781 void qh_setlarger(setT **oldsetp) {
782   int size= 1, *sizep;
783   setT *newset, *set, **setp, *oldset;
784   void **oldp, **newp;
785 
786   if (*oldsetp) {
787     oldset= *oldsetp;
788     SETreturnsize_(oldset, size);
789     qhmem.cntlarger++;
790     qhmem.totlarger += size+1;
791     newset= qh_setnew(2 * size);
792     oldp= SETaddr_(oldset, void);
793     newp= SETaddr_(newset, void);
794     memcpy((char *)newp, (char *)oldp, (size+1) * SETelemsize);
795     sizep= SETsizeaddr_(newset);
796     *sizep= size+1;
797     FOREACHset_((setT *)qhmem.tempstack) {
798       if (set == oldset)
799 	*(setp-1)= newset;
800     }
801     qh_setfree(oldsetp);
802   }else
803     newset= qh_setnew(3);
804   *oldsetp= newset;
805 } /* setlarger */
806 
807 
808 /*----------------------------------------
809 -setlast- return last element of set or NULL
810    set may be NULL
811 */
qh_setlast(setT * set)812 void *qh_setlast(setT *set) {
813   int size;
814 
815   if (set) {
816     size= *SETsizeaddr_(set);
817     if (!size)
818       return SETelem_(set, set->maxsize - 1);
819     else if (size > 1)
820       return SETelem_(set, size - 2);
821   }
822   return NULL;
823 } /* setlast */
824 
825 
826 /*----------------------------------------
827 -setnew- creates and allocates space for a set
828     setsize means the number of elements (NOT including the NULL terminator)
829     use qh_settemp/qh_setfreetemp if set is temporary
830 */
qh_setnew(int setsize)831 setT *qh_setnew(int setsize) {
832   setT *set;
833   int sizereceived, size;
834   void **freelistp;
835 
836   if (!setsize)
837     setsize++;
838   size= sizeof(setT) + setsize * SETelemsize;
839   if ((unsigned) size <= (unsigned) qhmem.LASTsize) {
840     qh_memalloc_(size, freelistp, set);
841     sizereceived= qhmem.sizetable[ qhmem.indextable[size]];
842     if (sizereceived > size)
843       setsize += (sizereceived - size)/SETelemsize;
844   }else
845     set= (setT *)qh_memalloc ((int)size);
846   set->maxsize= setsize;
847   set->e[setsize]= (void *) 1;
848   set->e[0]= NULL;
849   return (set);
850 } /* setnew */
851 
852 
853 /*----------------------------------------
854 -setnew_delnthsorted- creates a sorted set not containing nth element
855   the new set may have prepended undefined entries
856   set must be defined
857   checks nth
858   see also: setdelnthsorted
859 */
qh_setnew_delnthsorted(setT * set,int size,int nth,int prepend)860 setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend) {
861   setT *newset;
862   void **oldp, **newp;
863   int tailsize= size - nth -1, newsize;
864 
865   if (tailsize < 0) qhull_fatal(14);
866 
867   newsize= size-1 + prepend;
868   newset= qh_setnew(newsize);
869   // This (void *) cast was in the original, 1990s, pre-64-bit Pelican
870   newset->e[newset->maxsize]= reinterpret_cast<void *>(newsize+1);  /* may be overwritten */
871   oldp= SETaddr_(set, void);
872   newp= SETaddr_(newset, void) + prepend;
873   switch (nth) {
874   case 0:
875     break;
876   case 1:
877     *(newp++)= *oldp++;
878     break;
879   case 2:
880     *(newp++)= *oldp++;
881     *(newp++)= *oldp++;
882     break;
883   case 3:
884     *(newp++)= *oldp++;
885     *(newp++)= *oldp++;
886     *(newp++)= *oldp++;
887     break;
888   case 4:
889     *(newp++)= *oldp++;
890     *(newp++)= *oldp++;
891     *(newp++)= *oldp++;
892     *(newp++)= *oldp++;
893     break;
894   default:
895     memcpy((char *)newp, (char *)oldp, nth * SETelemsize);
896     newp += nth;
897     oldp += nth;
898     break;
899   }
900   oldp++;
901   switch (tailsize) {
902   case 0:
903     break;
904   case 1:
905     *(newp++)= *oldp++;
906     break;
907   case 2:
908     *(newp++)= *oldp++;
909     *(newp++)= *oldp++;
910     break;
911   case 3:
912     *(newp++)= *oldp++;
913     *(newp++)= *oldp++;
914     *(newp++)= *oldp++;
915     break;
916   case 4:
917     *(newp++)= *oldp++;
918     *(newp++)= *oldp++;
919     *(newp++)= *oldp++;
920     *(newp++)= *oldp++;
921     break;
922   default:
923     memcpy((char *)newp, (char *)oldp, tailsize * SETelemsize);
924     newp += tailsize;
925   }
926   *newp= NULL;
927   return(newset);
928 } /* setnew_delnthsorted */
929 
930 
931 /*----------------------------------------
932 -setprint- print set elements to fp
933 notes:
934   never errors
935 */
qh_setprint(FILE * fp,const char * string,setT * set)936 void qh_setprint(FILE *fp, const char *string, setT *set) {
937   int size, k;
938 
939   if (!set)
940     fprintf (fp, "%s set is null\n", string);
941   else {
942     SETreturnsize_(set, size);
943     //fprintf (fp, "%s set=%x maxsize=%d size=%d elems=",
944 	  //   string, (unsigned int) set, set->maxsize, size);
945     fprintf (fp, "%s set=%p maxsize=%d size=%d elems=",
946 	     string, static_cast<void *>(set), set->maxsize, size);
947     if (size > (int)set->maxsize)
948       size= set->maxsize+1;
949     for (k=0; k<size; k++)
950       fprintf(fp, " %p", set->e[k]);
951     fprintf(fp, "\n");
952   }
953 } /* setprint */
954 
955 /*----------------------------------------
956 -setreplace- replaces oldelem in set with newelem
957    errors if oldelem not in the set
958    if newelem is NULL then FOREACH no longer works
959 */
qh_setreplace(setT * set,void * oldelem,void * newelem)960 void qh_setreplace(setT *set, void *oldelem, void *newelem) {
961   void **elemp;
962 
963   elemp= SETaddr_(set, void);
964   while(*elemp != oldelem && *elemp)
965     elemp++;
966   if (*elemp)
967     *elemp= newelem;
968 
969   else qhull_fatal(15);
970 
971 } /* setreplace */
972 
973 
974 /*----------------------------------------
975 -setsize- returns the size of a set
976   same as SETreturnsize_(set)
977 */
qh_setsize(setT * set)978 int qh_setsize(setT *set) {
979   int size, *sizep;
980 
981   if (!set)
982     return (0);
983   sizep= SETsizeaddr_(set);
984   if ((size= *sizep)) {
985     size--;
986 
987     if (size > (int)set->maxsize) qhull_fatal(16);
988 
989   }else
990     size= set->maxsize;
991   return size;
992 } /* setsize */
993 
994 /*----------------------------------------
995 -settemp- return a stacked, temporary set
996   use settempfree or settempfree_all to release from qhmem.tempstack
997   see also qh_setnew
998 */
qh_settemp(int setsize)999 setT *qh_settemp(int setsize) {
1000   setT *newset;
1001 
1002   newset= qh_setnew (setsize);
1003   qh_setappend ((setT **)&qhmem.tempstack, newset);
1004   if (qhmem.IStracing >= 5)
1005     fprintf (qhmem.ferr, "qh_settemp: temp set %p of %d elements, depth %d\n",
1006 	     static_cast<void *>(newset),
1007 	     newset->maxsize, qh_setsize ((setT *)qhmem.tempstack));
1008   return newset;
1009 } /* settemp */
1010 
1011 /*----------------------------------------
1012 -settempfree- free temporary set at top of qhmem.tempstack
1013   nop if NULL
1014   errors if set not from previous qh_settemp
1015     locate source by T2 and find mis-matching qh_settemp
1016 */
qh_settempfree(setT ** set)1017 void qh_settempfree(setT **set) {
1018   setT *stackedset;
1019 
1020   if (!*set)
1021     return;
1022   stackedset= qh_settemppop ();
1023 
1024   if (stackedset != *set) qhull_fatal(17);
1025 
1026   qh_setfree (set);
1027 } /* settempfree */
1028 
1029 /*----------------------------------------
1030 -settempfree_all- free all temporary sets in qhmem.tempstack
1031 */
qh_settempfree_all(void)1032 void qh_settempfree_all(void) {
1033   setT *set, **setp;
1034 
1035   FOREACHset_((setT *)qhmem.tempstack)
1036     qh_setfree(&set);
1037   qh_setfree((setT **)&qhmem.tempstack);
1038 } /* settempfree_all */
1039 
1040 /*----------------------------------------
1041 -settemppop- pop and return temporary set from qhmem.tempstack (makes it permanent)
1042 */
qh_settemppop(void)1043 setT *qh_settemppop(void) {
1044   setT *stackedset;
1045 
1046   stackedset= (setT *)qh_setdellast((setT *)qhmem.tempstack);
1047 
1048   if (!stackedset) qhull_fatal(18);
1049 
1050   if (qhmem.IStracing >= 5)
1051     fprintf (qhmem.ferr, "qh_settemppop: depth %d temp set %p of %d elements\n",
1052 	     qh_setsize((setT *)qhmem.tempstack)+1, static_cast<void *>(stackedset),
1053 	     qh_setsize(stackedset));
1054   return stackedset;
1055 } /* settemppop */
1056 
1057 /*----------------------------------------
1058 -settemppush- push temporary set unto qhmem.tempstack (makes it temporary)
1059   duplicates settemp() for tracing
1060 */
qh_settemppush(setT * set)1061 void qh_settemppush(setT *set) {
1062 
1063   qh_setappend ((setT**)&qhmem.tempstack, set);
1064   if (qhmem.IStracing >= 5)
1065     fprintf (qhmem.ferr, "qh_settemppush: depth %d temp set %p of %d elements\n",
1066 	     qh_setsize((setT *)qhmem.tempstack), static_cast<void *>(set), qh_setsize(set));
1067 } /* settemppush */
1068 
1069 
1070 /*----------------------------------------
1071 -settruncate- truncate set to size elements
1072   set must be defined
1073 */
qh_settruncate(setT * set,int size)1074 void qh_settruncate (setT *set, int size) {
1075 
1076   if (size < 0 || size > (int)set->maxsize) qhull_fatal(19);
1077 
1078   // This (void *) cast was in the original, 1990s, pre-64-bit Pelican
1079   set->e[set->maxsize]= reinterpret_cast<void *>(size+1);   /* maybe overwritten */
1080   set->e[size]= NULL;
1081 } /* setruncate */
1082 
1083 /*----------------------------------------
1084 -setunique- add element if it isn't already
1085   returns 1 if it's appended
1086 */
qh_setunique(setT ** set,void * elem)1087 int qh_setunique (setT **set, void *elem) {
1088 
1089   if (!qh_setin (*set, elem)) {
1090     qh_setappend (set, elem);
1091     return 1;
1092   }
1093   return 0;
1094 } /* setunique */
1095 
1096 /*----------------------------------------
1097 -setzero- zero remainder of set and set its size
1098   set must be defined
1099 */
qh_setzero(setT * set,int index,int size)1100 void qh_setzero (setT *set, int index, int size) {
1101   int count;
1102 
1103   if (index < 0 || index >= size || size > (int)set->maxsize) qhull_fatal(20);
1104 
1105   // This (void *) cast was in the original, 1990s, pre-64-bit Pelican
1106   (set->e[set->maxsize])=  reinterpret_cast<void *>(size+1);  /* may be overwritten */
1107   count= size - index + 1;   /* +1 for NULL terminator */
1108   memset ((char *)SETelemaddr_(set, index, void), 0, count * sizeof(void *));
1109 } /* setzero */
1110 
1111 
1112 /*************************************************************************/
1113 /****************** implementation code from geom.c **********************/
1114 /*************************************************************************/
1115 
1116 
1117 /* geom.c -- geometric routines of qhull
1118 
1119    see README and geom.h
1120 
1121    copyright (c) 1993-1994 The Geometry Center
1122 */
1123 
1124 /*-------------------------------------------------
1125 -backnormal- solve for normal x using back substitution over rows U
1126      solves Ux=b where Ax=b and PA=LU
1127      b= [0,...,0,sign or 0]  (-1 if sign, else +1)
1128      last row of A= [0,...,0,1]
1129      assumes numrow == numcol-1
1130 returns:
1131      normal= x
1132      if can't divzero() for later normalization (qh MINdenom_2 and qh MINdenom_1_2),
1133          sets tail of normal to [...,sign,0,...], i.e., solves for b= [0...]
1134 	 sets nearzero, unless last row (i.e., hyperplane intersects [0,..,1])
1135 notes:
1136      1) Ly=Pb == y=b since P only permutes the 0's of b
1137      see Golub & van Loan 4.4-9 for back substitution
1138 */
qh_backnormal(realT ** rows,int numrow,int numcol,boolT sign,coordT * normal,boolT * nearzero)1139 void qh_backnormal (realT **rows, int numrow, int numcol, boolT sign,
1140   	coordT *normal, boolT *nearzero) {
1141   int i, j;
1142   coordT *normalp, *normal_tail, *ai, *ak;
1143   realT diagonal;
1144   boolT waszero;
1145   int zerocol=-1;
1146 
1147   normalp= normal + numcol - 1;
1148   *normalp--= (sign ? -1.0 : 1.0);
1149   for(i= numrow; i--; ) {
1150     *normalp= 0.0;
1151     ai= rows[i] + i + 1;
1152     ak= normalp+1;
1153     for(j= i+1; j < numcol; j++)
1154       *normalp -= *ai++ * *ak++;
1155     diagonal= (rows[i])[i];
1156     if (fabs_(diagonal) > qh MINdenom_2)
1157       *(normalp--) /= diagonal;
1158     else {
1159       waszero= False;
1160       *normalp= qh_divzero (*normalp, diagonal, qh MINdenom_1_2, &waszero);
1161       if (waszero) {
1162         zerocol= i;
1163 	*(normalp--)= (sign ? -1.0 : 1.0);
1164 	for (normal_tail= normalp+2; normal_tail < normal + numcol; normal_tail++)
1165 	  *normal_tail= 0.0;
1166       }else
1167 	normalp--;
1168     }
1169   }
1170   if (zerocol != -1) {
1171     zzinc_(Zback0);
1172     *nearzero= True;
1173     trace4((qh ferr, "qh_backnormal: zero diagonal at column %d.\n", i));
1174   }
1175 } /* backnormal */
1176 
1177 /*-------------------------------------------------
1178 -crossproduct- of 2 dim vectors, C= A x B
1179     from Glasner, Graphics Gems I, p. 639
1180     NOTE: only defined for dim==3
1181 */
qh_crossproduct(int dim,realT vecA[3],realT vecB[3],realT vecC[3])1182 void qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
1183 
1184   if (dim == 3) {
1185     vecC[0]=   det2_(vecA[1], vecA[2],
1186 		     vecB[1], vecB[2]);
1187     vecC[1]= - det2_(vecA[0], vecA[2],
1188 		     vecB[0], vecB[2]);
1189     vecC[2]=   det2_(vecA[0], vecA[1],
1190 		     vecB[0], vecB[1]);
1191   }
1192 } /* vcross */
1193 
1194 /*-------------------------------------------------
1195 -determinant- compute the determinant of a square matrix
1196   rows= row vectors
1197   uses qh NEARzero to test for degenerate matrices
1198     this does look right, probably no easy way of doing it
1199 returns:
1200   determinant
1201   overwrites rows and the matrix
1202   nearzero set if degenerate
1203 */
qh_determinant(realT ** rows,int dim,boolT * nearzero)1204 realT qh_determinant (realT **rows, int dim, boolT *nearzero) {
1205   realT det=0;
1206   int i;
1207   boolT sign= False;
1208 
1209   *nearzero= False;
1210   if (dim < 2) { qhull_fatal(21); }
1211   else if (dim == 2) {
1212     det= det2_(rows[0][0], rows[0][1],
1213 		 rows[1][0], rows[1][1]);
1214     if (fabs_(det) < qh NEARzero[1])  /* not really correct, what should this be? */
1215       *nearzero= True;
1216   }else if (dim == 3) {
1217     det= det3_(rows[0][0], rows[0][1], rows[0][2],
1218 		 rows[1][0], rows[1][1], rows[1][2],
1219 		 rows[2][0], rows[2][1], rows[2][2]);
1220     if (fabs_(det) < qh NEARzero[2])  /* not really correct, what should this be? */
1221       *nearzero= True;
1222   }else {
1223     qh_gausselim(rows, dim, dim, &sign, nearzero);  /* if nearzero, diagonal still ok*/
1224     det= 1.0;
1225     for (i= dim; i--; )
1226       det *= (rows[i])[i];
1227     if (sign)
1228       det= -det;
1229   }
1230   return det;
1231 } /* determinant */
1232 
1233 /*-------------------------------------------------
1234 -detsimplex- compute determinant of a simplex with point apex and base points
1235    uses qh gm_matrix/qh gm_row (assumes they're big enough)
1236    uses dim coordinates of point and vertex->point
1237 returns:
1238    if dim == 2 or 3
1239      nearzero iff determinant < qh NEARzero[dim-1]  (not quite correct)
1240    if dim >= 4
1241      nearzero iff diagonal[k] < qh NEARzero[k]
1242 */
qh_detsimplex(pointT * apex,setT * points,int dim,boolT * nearzero)1243 realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero) {
1244   pointT *coorda, *coordp, *gmcoord, *point, **pointp;
1245   coordT **rows;
1246   int k,  i=0;
1247   realT det= 0.0;
1248 
1249   zinc_(Zdetsimplex);
1250   gmcoord= qh gm_matrix;
1251   rows= qh gm_row;
1252   FOREACHpoint_(points) {
1253     if (i == dim)
1254       break;
1255     rows[i++]= gmcoord;
1256     coordp= point;
1257     coorda= apex;
1258     for(k= dim; k--; )
1259       *(gmcoord++)= *coordp++ - *coorda++;
1260   }
1261   if (i < dim) { qhull_fatal(22); }
1262   det= qh_determinant (rows, dim, nearzero);
1263   trace2((qh ferr, "qh_detsimplex: det=%2.2g for point p%d, dimension %d, nearzero? %d\n",
1264 	  det, qh_pointid(apex), dim, *nearzero));
1265   return det;
1266 } /* detsimplex */
1267 
1268 /*-------------------------------------------
1269 -distplane- get distance from point to facet
1270 returns:
1271     positive if point is above facet (i.e., outside)
1272     can not qhull_fatal (for sortfacets)
1273 */
qh_distplane(pointT * point,facetT * facet,realT * dist)1274 void qh_distplane (pointT *point, facetT *facet, realT *dist) {
1275   coordT *normal= facet->normal, *coordp, randr;
1276   int k;
1277 
1278   switch(qh hull_dim){
1279   case 2:
1280     *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1];
1281     break;
1282   case 3:
1283     *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2];
1284     break;
1285   case 4:
1286     *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3];
1287     break;
1288   case 5:
1289     *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4];
1290     break;
1291   case 6:
1292     *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5];
1293     break;
1294   case 7:
1295     *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6];
1296     break;
1297   case 8:
1298     *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6]+point[7]*normal[7];
1299     break;
1300   default:
1301     *dist= facet->offset;
1302     coordp= point;
1303     for (k= qh hull_dim; k--; )
1304       *dist += *coordp++ * *normal++;
1305     break;
1306   }
1307   zinc_(Zdistplane);
1308   if (!qh RANDOMdist && qh IStracing < 4)
1309     return;
1310   if (qh RANDOMdist) {
1311     randr= qh_RANDOMint;
1312     *dist += (2.0 * randr / qh_RANDOMmax - 1.0) *
1313       qh RANDOMfactor * qh maxmaxcoord;
1314   }
1315   /*
1316   if (qh IStracing >= 4) {
1317     fprintf (qh ferr, "qh_distplane: ");
1318     fprintf (qh ferr, qh_REAL_1, *dist);
1319     fprintf (qh ferr, "from p%d to f%d\n", qh_pointid(point), facet->id);
1320   }
1321   */
1322   return;
1323 } /* distplane */
1324 
1325 
1326 /*--------------------------------------------------
1327 -divzero -- divide by a number that's nearly zero
1328   mindenom1= minimum denominator for dividing into 1.0
1329 returns:
1330   zerodiv and 0.0 if it would overflow
1331 */
qh_divzero(realT numer,realT denom,realT mindenom1,boolT * zerodiv)1332 realT qh_divzero (realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
1333   realT temp, numerx, denomx;
1334 
1335 
1336   if (numer < mindenom1 && numer > -mindenom1) {
1337     numerx= fabs_(numer);
1338     denomx= fabs_(denom);
1339     if (numerx < denomx) {
1340       *zerodiv= False;
1341       return numer/denom;
1342     }else {
1343       *zerodiv= True;
1344       return 0.0;
1345     }
1346   }
1347   temp= denom/numer;
1348   if (temp > mindenom1 || temp < -mindenom1) {
1349     *zerodiv= False;
1350     return numer/denom;
1351   }else {
1352     *zerodiv= True;
1353     return 0.0;
1354   }
1355 } /* divzero */
1356 
1357 
1358 /*-------------------------------------------------
1359 -facetcenter- return Voronoi center for a facet's vertices
1360 */
qh_facetcenter(setT * vertices)1361 pointT *qh_facetcenter (setT *vertices) {
1362   setT *points= qh_settemp (qh_setsize (vertices));
1363   vertexT *vertex, **vertexp;
1364   pointT *center;
1365 
1366   FOREACHvertex_(vertices)
1367     qh_setappend (&points, vertex->point);
1368   center= qh_voronoi_center (qh hull_dim-1, points);
1369   qh_settempfree (&points);
1370   return center;
1371 } /* facetcenter */
1372 
1373 /*-------------------------------------------------
1374 -findbest- find best facet for point starting at a facet (not flipped!)
1375   if bestoutside, searches all facets else stops at first outside
1376     MINoutside is DISTround in precise case
1377   if firstid, searches facets with ids >= firstid
1378     searches old facets if bestoutside || (not outside and imprecise)
1379   searches all neighbors of coplanar and flipped facets
1380     searchdist is arbitrarily set to min_vertex+max_outside+DISTround
1381        max_outside is needed for setting facet->maxoutside
1382 returns:
1383   if !firstid, updates facet->maxoutside for good, visited facets
1384   distance to facet
1385   isoutside true if point is outside of facet
1386   bumps visit_id and seen flags
1387 notes:
1388   uses visitid and seen
1389   statistics collected here for partitions, caller does outside/coplanar
1390   caller traces the results
1391   #2 after setfacetplane in D3, optimized for outside points and !bestoutside
1392   #1 when merging in D3
1393   see also partitionall()
1394 notes on searchdist:
1395   searchdist needed since vertex neighbors can be geometric neighbors of facet
1396   if searchdist=DISTround, gets stuck for rbox 50 W1e-3 D7 | qhull A-0.99 W0.2
1397   if !BESToutside and merging, gets stuck for rbox 1000 W8e-6 | qhull C-0
1398     because nearly coplanar widens when the point is outside of the facets
1399   searching all new facets does not prevent !BESToutside getting stuck
1400   check_maxoutside can also get stuck, should keep coplanars
1401 */
qh_findbest(pointT * point,facetT * facet,boolT bestoutside,unsigned firstid,realT * dist,boolT * isoutside,int * numpart)1402 facetT *qh_findbest (pointT *point, facetT *facet, boolT bestoutside,
1403 	   unsigned firstid, realT *dist, boolT *isoutside, int *numpart) {
1404   realT bestdist, searchdist;
1405   facetT *neighbor, **neighborp, *bestfacet;
1406   setT *search= NULL;
1407   int oldtrace= qh IStracing;
1408   boolT checkmax= (boolT)(bestoutside && !firstid && qh_MAXoutside
1409     && (qh MERGING || qh APPROXhull));
1410 
1411   if (qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid (point)) {
1412     qh IStracing= qh TRACElevel;
1413     /*
1414     fprintf (qh ferr, "qh_findbest: point p%d starting at f%d bestoutside? %d firstid %d\n",
1415 	     qh TRACEpoint, facet->id, bestoutside, firstid);
1416     fprintf (qh ferr, "  Last point added to hull was p%d.", qh furthest_id);
1417     fprintf(qh ferr, "  Last merge was #%d.\n", zzval_(Ztotmerge));
1418     */
1419   }
1420   searchdist= - qh min_vertex + qh max_outside + 2* qh DISTround;
1421   *isoutside= True;
1422   *numpart= 1;
1423   qh_distplane (point, facet, dist);
1424   bestdist= *dist;
1425   bestfacet= facet;
1426   if (!bestoutside &&  *dist >= qh MINoutside)
1427     goto LABELreturn_best;
1428 #if qh_MAXoutside
1429   if (checkmax && (!qh ONLYgood || facet->good) && *dist > facet->maxoutside)
1430     facet->maxoutside= *dist;
1431 #endif
1432   facet->visitid= ++qh visit_id;
1433   facet->seen= False;
1434   if (True) {                   /* directed search for bestfacet */
1435 LABELrepeat:			   /* facet->seen if clearly worse */
1436     trace4((qh ferr, "qh_findbest: neighbors of f%d\n", facet->id));
1437     FOREACHneighbor_(facet) {
1438       if ((int)neighbor->visitid == qh visit_id)
1439         continue;
1440       if (neighbor->id < firstid) {
1441         neighbor->seen= True;
1442         continue;
1443       }
1444       neighbor->visitid= qh visit_id;
1445       neighbor->seen= False;
1446       if (neighbor->flipped)
1447         continue;
1448       (*numpart)++;
1449       qh_distplane (point, neighbor, dist);
1450       if (!bestoutside && *dist >= qh MINoutside) {
1451 	bestfacet= neighbor;
1452 	goto LABELreturn_best;
1453       }
1454 #if qh_MAXoutside
1455       if (checkmax && (!qh ONLYgood || neighbor->good)
1456           && *dist > neighbor->maxoutside)
1457         neighbor->maxoutside= *dist;
1458 #endif
1459       if (*dist >= bestdist) {  /* >= for exact coplanar */
1460         bestdist= *dist;
1461         bestfacet= neighbor;
1462         if (*dist > bestdist + searchdist)
1463           facet->seen= True;
1464         facet= neighbor;
1465         goto LABELrepeat;
1466       }else if (*dist < bestdist - searchdist)
1467         neighbor->seen= True;
1468     }
1469   }
1470   do {                   /* search horizon of facet */
1471     FOREACHneighbor_(facet) {
1472       if ((int)neighbor->visitid == qh visit_id) {
1473         if (!neighbor->seen) {
1474           neighbor->seen= True;
1475           if (!search)
1476             search= qh_settemp (qh TEMPsize);
1477           qh_setappend (&search, neighbor);
1478         }
1479         continue;
1480       }
1481       neighbor->visitid= qh visit_id;
1482       neighbor->seen= True;
1483       if (neighbor->flipped) {
1484         if (!search)
1485           search= qh_settemp (qh TEMPsize);
1486         qh_setappend (&search, neighbor);
1487         continue;
1488       }
1489       if (neighbor->id < firstid) {
1490         if (!(bestoutside+qh APPROXhull+qh PREmerge))
1491           continue;
1492       }else
1493         zinc_(Zpartneighbor);
1494       (*numpart)++;
1495       qh_distplane (point, neighbor, dist);
1496       if (!bestoutside && *dist >= qh MINoutside) {
1497 	bestfacet= neighbor;
1498 	goto LABELreturn_best;
1499       }
1500 #if qh_MAXoutside
1501       if (checkmax && *dist > neighbor->maxoutside)
1502         neighbor->maxoutside= *dist;
1503 #endif
1504       if (*dist >= bestdist - searchdist) {
1505         if (!search)
1506           search= qh_settemp (qh TEMPsize);
1507         qh_setappend (&search, neighbor);
1508         if (*dist > bestdist) {
1509           bestdist= *dist;
1510           bestfacet= neighbor;
1511         }
1512       }
1513     }
1514   }while ((facet= (facetT *)qh_setdellast (search)));
1515   *dist= bestdist;
1516   if (!bestoutside || bestdist < qh MINoutside)
1517     *isoutside= False;
1518 LABELreturn_best:
1519   if (search)
1520     qh_settempfree (&search);
1521   qh IStracing= oldtrace;
1522   return bestfacet;
1523 }  /* findbest */
1524 
1525 
1526 /*-------------------------------------------------
1527 -findgooddist- find best good facet visible for point from facetA
1528   assumes facetA is visible from point
1529   uses qh visit_id and qh visible_list (but doesn't set visible)
1530 returns:
1531   furthest distance to good facet, if any
1532   bumps visit_id and seen flags
1533 */
qh_findgooddist(pointT * point,facetT * facetA,realT * distp)1534 facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp) {
1535   realT bestdist= -REALmax, dist;
1536   facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
1537   boolT goodseen= False;
1538 
1539   if (facetA->good) {
1540     zinc_(Zverifypart);
1541     qh_distplane (point, facetA, &bestdist);
1542     bestfacet= facetA;
1543     goodseen= True;
1544   }
1545   qh_removefacet (facetA);
1546   qh_appendfacet (facetA);
1547   qh visible_list= facetA;
1548   facetA->visitid= ++qh visit_id;
1549   FORALLfacet_(qh visible_list) {
1550     FOREACHneighbor_(facet) {
1551       if ((int)neighbor->visitid == qh visit_id)
1552         continue;
1553       neighbor->visitid= qh visit_id;
1554       if (goodseen && !neighbor->good)
1555         continue;
1556       zinc_(Zverifypart);
1557       qh_distplane (point, neighbor, &dist);
1558       if (dist > 0) {
1559         qh_removefacet (neighbor);
1560         qh_appendfacet (neighbor);
1561         if (neighbor->good) {
1562           goodseen= True;
1563           if (dist > bestdist) {
1564             bestdist= dist;
1565             bestfacet= neighbor;
1566           }
1567         }
1568       }
1569     }
1570   }
1571   if (bestfacet) {
1572     *distp= bestdist;
1573     trace2((qh ferr, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
1574       qh_pointid(point), bestdist, bestfacet->id));
1575     return bestfacet;
1576   }
1577   trace4((qh ferr, "qh_findgooddist: no good facet for p%d above f%d\n",
1578       qh_pointid(point), facetA->id));
1579   return NULL;
1580 }  /* findgooddist */
1581 
1582 /*-------------------------------------------------
1583 -gausselim- Gaussian elimination with partial pivoting
1584   coordT data in rows
1585   assumes numrow <= numcol
1586 returns:
1587   rows is upper triangular (includes row exchanges)
1588   flips sign for each row exchange
1589   sets nearzero if pivot[k] < qh NEARzero[k], else False.
1590     if nearzero, the determinant's sign may be incorrect.
1591 */
qh_gausselim(realT ** rows,int numrow,int numcol,boolT * sign,boolT * nearzero)1592 void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero) {
1593   realT *ai, *ak, *rowp, *pivotrow;
1594   realT n, pivot, pivot_abs= 0.0, temp;
1595   int i, j, k, pivoti, flip=0, tempint;
1596 
1597   *nearzero= False;
1598   for(k= 0; k < numrow; k++) {
1599     pivot_abs= fabs_((rows[k])[k]);
1600     pivoti= k;
1601     for(i= k+1; i < numrow; i++) {
1602       if ((temp= fabs_((rows[i])[k])) > pivot_abs) {
1603 	pivot_abs= temp;
1604 	pivoti= i;
1605       }
1606     }
1607     if (pivoti != k) {
1608       rowp= rows[pivoti];
1609       rows[pivoti]= rows[k];
1610       rows[k]= rowp;
1611       tempint = (int)*sign;
1612       tempint ^= 1;
1613       *sign = (boolT)tempint;
1614       flip ^= 1;
1615     }
1616     if (pivot_abs <= qh NEARzero[k]) {
1617       *nearzero= True;
1618       if (pivot_abs == 0.0) {   /* remainder of column == 0 */
1619 
1620 	/*
1621 	if (qh IStracing >= 4) {
1622 	  fprintf (qh ferr, "qh_gausselim: 0 pivot at column %d. (%2.2g < %2.2g)\n", k, pivot_abs, qh DISTround);
1623 	  qh_printmatrix (qh ferr, "Matrix:", rows, numrow, numcol);
1624 	}
1625 	*/
1626 
1627 	zzinc_(Zgauss0);
1628 	goto LABELnextcol;
1629       }
1630     }
1631     pivotrow= rows[k] + k;
1632     pivot= *pivotrow++;  /* signed value of pivot, and remainder of row */
1633     for(i= k+1; i < numrow; i++) {
1634       ai= rows[i] + k;
1635       ak= pivotrow;
1636       n= (*ai++)/pivot;   /* divzero() not needed since |pivot| >= |*ai| */
1637       for(j= numcol - (k+1); j--; )
1638 	*ai++ -= n * *ak++;
1639     }
1640   LABELnextcol:
1641     ;
1642   }
1643   wmin_(Wmindenom, pivot_abs);  /* last pivot element */
1644   if (qh IStracing >= 5)
1645     qh_printmatrix (qh ferr, "qh_gausselem: result", rows, numrow, numcol);
1646 } /* gausselim */
1647 
1648 
1649 /*----------------------------------------------
1650 -getangle- returns the dot product of two, qh hull_dim vectors
1651   may be > 1.0 or < -1.0
1652 */
qh_getangle(pointT * vect1,pointT * vect2)1653 realT qh_getangle(pointT *vect1, pointT *vect2) {
1654   realT angle= 0;
1655   int k;
1656 
1657   for(k= qh hull_dim; k--; )
1658     angle += *vect1++ * *vect2++;
1659   trace4((qh ferr, "qh_getangle: %2.2g\n", angle));
1660   return(angle);
1661 } /* getangle */
1662 
1663 
1664 /*----------------------------------------------
1665 -getcenter-  gets arithmetic center of a set of vertices as a new point
1666   assumes normal_size is in short memory
1667 */
qh_getcenter(setT * vertices)1668 pointT *qh_getcenter(setT *vertices) {
1669   int k;
1670   pointT *center, *coord;
1671   vertexT *vertex, **vertexp;
1672   int count= qh_setsize(vertices);
1673 
1674   if (count < 2) qhull_fatal(23);
1675 
1676   center= (pointT *)qh_memalloc(qh normal_size);
1677   for (k=0; k < qh hull_dim; k++) {
1678     coord= center+k;
1679     *coord= 0.0;
1680     FOREACHvertex_(vertices)
1681       *coord += vertex->point[k];
1682     *coord /= count;
1683   }
1684   return(center);
1685 } /* getcenter */
1686 
1687 
1688 /*----------------------------------------------
1689 -getcentrum- returns the centrum for a facet as a new point
1690   assumes normal_size is in short memory
1691 */
qh_getcentrum(facetT * facet)1692 pointT *qh_getcentrum(facetT *facet) {
1693   realT dist;
1694   pointT *centrum, *point;
1695 
1696   point= qh_getcenter(facet->vertices);
1697   zinc_(Zcentrumtests);
1698   qh_distplane (point, facet, &dist);
1699   centrum= qh_projectpoint(point, facet, dist);
1700   qh_memfree(point, qh normal_size);
1701   trace4((qh ferr, "qh_getcentrum: for f%d, %d vertices dist= %2.2g\n",
1702 	  facet->id, qh_setsize(facet->vertices), dist));
1703   return centrum;
1704 } /* getcentrum */
1705 
1706 
1707 /*-------------------------------------------------
1708 -gram_schmidt- implements Gram-Schmidt orthogonalization by rows
1709    overwrites rows[dim][dim]
1710 returns:
1711    false if gets a zero norm
1712 notes:
1713    see Golub & van Loan Algorithm 6.2-2
1714    overflow due to small divisors not handled
1715 */
qh_gram_schmidt(int dim,realT ** row)1716 boolT qh_gram_schmidt(int dim, realT **row) {
1717   realT *rowi, *rowj, norm;
1718   int i, j, k;
1719 
1720   for(i=0; i < dim; i++) {
1721     rowi= row[i];
1722     for (norm= 0.0, k= dim; k--; rowi++)
1723       norm += *rowi * *rowi;
1724     norm= sqrt(norm);
1725     wmin_(Wmindenom, norm);
1726     if (norm == 0.0)  /* either 0 or overflow due to sqrt */
1727       return False;
1728     for(k= dim; k--; )
1729       *(--rowi) /= norm;
1730     for(j= i+1; j < dim; j++) {
1731       rowj= row[j];
1732       for(norm= 0.0, k=dim; k--; )
1733 	norm += *rowi++ * *rowj++;
1734       for(k=dim; k--; )
1735 	*(--rowj) -= *(--rowi) * norm;
1736     }
1737   }
1738   return True;
1739 } /* gram_schmidt */
1740 
1741 
1742 
1743 
1744 /*--------------------------------------------------
1745 -inthresholds- return True if normal within qh lower_/upper_threshold
1746 returns:
1747   angle cos to a threshold border (may be NULL, invalid if qh SPLITthresholds)
1748 */
qh_inthresholds(coordT * normal,realT * angle)1749 boolT qh_inthresholds (coordT *normal, realT *angle) {
1750   boolT within= True;
1751   int k;
1752 
1753   if (angle)
1754     *angle= 0.0;
1755   for(k= 0; k < qh hull_dim; k++) {
1756     if (qh lower_threshold[k] > -REALmax/2) {
1757       if (normal[k] < qh lower_threshold[k])
1758         within= False;
1759       if (angle)
1760         *angle += normal[k] * qh lower_threshold[k];
1761     }
1762     if (qh upper_threshold[k] < REALmax/2) {
1763       if (normal[k] > qh upper_threshold[k])
1764         within= False;
1765       if (angle)
1766         *angle += normal[k] * qh upper_threshold[k];
1767     }
1768   }
1769   return within;
1770 } /* inthresholds */
1771 
1772 
1773 /*--------------------------------------------------
1774 -maxabsval -- return pointer to maximum absolute value of a dim vector
1775    returns NULL if dim==0
1776 */
qh_maxabsval(realT * normal,int dim)1777 realT *qh_maxabsval (realT *normal, int dim) {
1778   realT maxval= -REALmax;
1779   realT *maxp= NULL, *colp, absval;
1780   int k;
1781 
1782   for (k= dim, colp= normal; k--; colp++) {
1783     absval= fabs_(*colp);
1784     if (absval > maxval) {
1785       maxval= absval;
1786       maxp= colp;
1787     }
1788   }
1789   return maxp;
1790 } /* maxabsval */
1791 
1792 
1793 /*-------------------------------------------------
1794 -maxmin- collects the maximum and minimum points of input into a set
1795   determines maximum roundoff errors
1796 returns:
1797   returns a temporary set, without qh GOODpoint
1798   points are not unique
1799 */
qh_maxmin(pointT * points,int numpoints,int dimension)1800 setT *qh_maxmin(pointT *points, int numpoints, int dimension) {
1801   int k;
1802   realT maxsum= 0.0, maxcoord, temp, maxdistsum;
1803   realT maxneg= REALmax, maxpos= -REALmax;
1804   pointT *minimum, *maximum, *point, *pointtemp;
1805   setT *set;
1806 
1807   set= qh_settemp(2*dimension);
1808   for(k= 0; k < dimension; k++) {
1809     if (points == qh GOODpointp)
1810       minimum= maximum= points + qh hull_dim;
1811     else
1812       minimum= maximum= points;
1813     FORALLpoint_(points, numpoints) {
1814       if (point == qh GOODpointp)
1815 	continue;
1816       if (maximum[k] < point[k])
1817 	maximum= point;
1818       else if (minimum[k] > point[k])
1819 	minimum= point;
1820     }
1821     maxcoord= fmax_(maximum[k], -minimum[k]);
1822     if (qh GOODpointp) {
1823       temp= fmax_(qh GOODpointp[k], -qh GOODpointp[k]);
1824       maximize_(maxcoord, temp);
1825     }
1826     maximize_(qh maxmaxcoord, maxcoord);
1827     maxsum += maxcoord;
1828     maximize_(maxpos, maximum[k]);
1829     minimize_(maxneg, minimum[k]);
1830     qh_setappend (&set, maximum);
1831     qh_setappend (&set, minimum);
1832     /* calculation of qh NEARzero is based on error formula 4.4-13 of
1833        Golub & van Loan, authors say n^3 can be ignored and 10 be used in
1834        place of rho */
1835     qh NEARzero[k]= 80 * maxsum * REALepsilon;
1836   }
1837   /* calculate roundoff error according to
1838      Lemma 3.2-1 of Golub and van Loan "Matrix Computation"
1839      use sqrt(dim) since one vector is normalized */
1840   maxdistsum= sqrt (qh hull_dim) * qh maxmaxcoord;
1841   if (!qh SETroundoff) {
1842     qh DISTround= REALepsilon * (qh hull_dim * maxdistsum * 1.01
1843 			   	       + qh maxmaxcoord);  /* for offset */
1844     if (qh RANDOMdist)
1845       qh DISTround += qh RANDOMfactor * qh maxmaxcoord;
1846   }
1847   qh MINdenom= qh MINdenom_1 * qh maxmaxcoord;
1848   qh MINdenom_1_2= sqrt (qh MINdenom_1 * qh hull_dim) ;  /* if will be normalized */
1849   qh MINdenom_2= qh MINdenom_1_2 * qh maxmaxcoord;
1850   if (qh premerge_cos < REALmax/2)      /* for inner product */
1851     qh premerge_cos -= 1.01 * qh hull_dim * REALepsilon;
1852   if (qh postmerge_cos < REALmax/2)
1853     qh postmerge_cos -= 1.01 * qh hull_dim * REALepsilon;
1854   qh premerge_centrum += 2 * qh DISTround;    /*2 for centrum and distplane()*/
1855   qh postmerge_centrum += 2 * qh DISTround;
1856   { /* compute ONEmerge, max vertex offset for merging simplicial facets */
1857     realT maxangle= 1.0, maxrho;
1858 
1859     minimize_(maxangle, qh premerge_cos);
1860     minimize_(maxangle, qh postmerge_cos);
1861     /* max diameter * sin theta + DISTround for vertex to its hyperplane */
1862     qh ONEmerge= sqrt (qh hull_dim) * (maxpos - maxneg) *
1863       sqrt (1.0 - maxangle * maxangle) + qh DISTround;
1864     maxrho= qh hull_dim * qh premerge_centrum + qh DISTround;
1865     maximize_(qh ONEmerge, maxrho);
1866     maxrho= qh hull_dim * qh postmerge_centrum + qh DISTround;
1867     maximize_(qh ONEmerge, maxrho);
1868   }
1869   if (!qh APPROXhull) {             /* user may specify qh MINoutside */
1870     qh MINoutside= qh premerge_centrum - qh DISTround;
1871     if (qh premerge_cos < REALmax/2)
1872       maximize_(qh MINoutside, (1- qh premerge_cos) * qh maxmaxcoord);
1873   }
1874   if (qh MINvisible > REALmax/2)
1875     qh MINvisible= qh DISTround;
1876 
1877   /*
1878   if (qh MINvisible > qh MINoutside + 3*REALepsilon && !qh BESToutside &&
1879       !qh FORCEoutput)
1880     fprintf (qh ferr, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g.  Flipped facets are likely.\n",
1881 	     qh MINvisible, qh MINoutside);
1882 	     */
1883 
1884   qh max_vertex= qh DISTround;
1885   qh min_vertex= -qh DISTround;
1886 
1887   /*
1888   if (qh IStracing >=1)
1889     qh_printpoints (qh ferr, "qh_maxmin: found the max and min points (by dim):", set);
1890     */
1891 
1892   /* numeric constants reported in printsummary */
1893   return(set);
1894 } /* maxmin */
1895 
1896 
1897 /*-------------------------------------------------
1898 -maxsimplex- determines maximum simplex for a set of points
1899   assumes at least pointsneeded points in points
1900   skips qh GOODpointp (assumes that it isn't in maxpoints)
1901   starts from points already in simplex
1902 returns:
1903   temporary set of dim+1 points
1904 notes:
1905   maximizes determinate for x,y,z,w, etc.
1906   uses maxpoints as long as determinate is clearly non-zero
1907 */
qh_maxsimplex(int dim,setT * maxpoints,pointT * points,int numpoints,setT ** simplex)1908 void qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
1909   pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
1910   boolT nearzero, maxnearzero= False;
1911   int k, sizinit;
1912   realT maxdet= -REALmax, det, mincoord= REALmax, maxcoord= -REALmax;
1913 
1914   sizinit= qh_setsize (*simplex);
1915   if (sizinit < 2) {
1916     if (qh_setsize (maxpoints) >= 2) {
1917       FOREACHpoint_(maxpoints) {
1918 
1919         if (maxcoord < point[0]) {
1920           maxcoord= point[0];
1921           maxx= point;
1922         }
1923 	if (mincoord > point[0]) {
1924           mincoord= point[0];
1925           minx= point;
1926         }
1927       }
1928     }else {
1929       FORALLpoint_(points, numpoints) {
1930 	if (point == qh GOODpointp)
1931 	  continue;
1932         if (maxcoord < point[0]) {
1933 	  maxcoord= point[0];
1934           maxx= point;
1935         }
1936 	if (mincoord > point[0]) {
1937           mincoord= point[0];
1938           minx= point;
1939 	}
1940       }
1941     }
1942     qh_setunique (simplex, minx);
1943     if (qh_setsize (*simplex) < 2)
1944       qh_setunique (simplex, maxx);
1945     sizinit= qh_setsize (*simplex);
1946 
1947     if (sizinit < 2) qhull_fatal(24);
1948   }
1949   for(k= sizinit; k < dim+1; k++) {
1950     maxpoint= NULL;
1951     maxdet= -REALmax;
1952     FOREACHpoint_(maxpoints) {
1953       if (!qh_setin (*simplex, point)) {
1954         det= qh_detsimplex(point, *simplex, k, &nearzero);
1955         if ((det= fabs_(det)) > maxdet) {
1956 	  maxdet= det;
1957           maxpoint= point;
1958 	  maxnearzero= nearzero;
1959         }
1960       }
1961     }
1962     if (!maxpoint || maxnearzero) {
1963       zinc_(Zsearchpoints);
1964       if (!maxpoint) {
1965         trace0((qh ferr, "qh_maxsimplex: searching all points for %d-th initial vertex\n", k));
1966       }else {
1967         trace0((qh ferr, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g\n",
1968 		k+1, qh_pointid(maxpoint), maxdet));
1969       }
1970       FORALLpoint_(points, numpoints) {
1971 	if (point == qh GOODpointp)
1972 	  continue;
1973         if (!qh_setin (*simplex, point)) {
1974           det= qh_detsimplex(point, *simplex, k, &nearzero);
1975           if ((det= fabs_(det)) > maxdet) {
1976 	    maxdet= det;
1977             maxpoint= point;
1978 	    maxnearzero= nearzero;
1979 	  }
1980         }
1981       }
1982     } /* !maxpoint */
1983     if (!maxpoint) qhull_fatal(25);
1984 
1985     qh_setappend(simplex, maxpoint);
1986     trace1((qh ferr, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%2.2g\n",
1987 	    qh_pointid(maxpoint), k, maxdet));
1988   }
1989 } /* maxsimplex */
1990 
1991 /*--------------------------------------------------
1992 -minabsval -- return min absolute value of a dim vector
1993 */
qh_minabsval(realT * normal,int dim)1994 realT qh_minabsval (realT *normal, int dim) {
1995   realT minval= 0;
1996   realT maxval= 0;
1997   realT *colp;
1998   int k;
1999 
2000   for (k= dim, colp= normal; k--; colp++) {
2001     maximize_(maxval, *colp);
2002     minimize_(minval, *colp);
2003   }
2004   return fmax_(maxval, -minval);
2005 } /* maxabsval */
2006 
2007 
2008 
2009 /*--------------------------------------------------
2010 -normalize -- normalize a vector
2011    qh MINdenom/MINdenom1 upper limits for divide overflow
2012 returns:
2013     normalized vector
2014     flips sign if !toporient
2015     if zero norm
2016        sets all elements to sqrt(1.0/dim)
2017     if divide by zero (divzero ())
2018        sets largest element to +/-1
2019        bumps Znearlysingular
2020 */
qh_normalize(coordT * normal,int dim,boolT toporient)2021 void qh_normalize (coordT *normal, int dim, boolT toporient) {
2022   int k;
2023   realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3;
2024   boolT zerodiv;
2025 
2026   norm1= normal+1;
2027   norm2= normal+2;
2028   norm3= normal+3;
2029   if (dim == 2)
2030     norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1));
2031   else if (dim == 3)
2032     norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2));
2033   else if (dim == 4) {
2034     norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
2035                + (*norm3)*(*norm3));
2036   }else if (dim > 4) {
2037     norm= (*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
2038                + (*norm3)*(*norm3);
2039     for (k= dim-4, colp= normal+4; k--; colp++)
2040       norm += (*colp) * (*colp);
2041     norm= sqrt(norm);
2042   }
2043   wmin_(Wmindenom, norm);
2044   if (norm > qh MINdenom) {
2045     if (!toporient)
2046       norm= -norm;
2047     *normal /= norm;
2048     *norm1 /= norm;
2049     if (dim == 2)
2050       ; /* all done */
2051     else if (dim == 3)
2052       *norm2 /= norm;
2053     else if (dim == 4) {
2054       *norm2 /= norm;
2055       *norm3 /= norm;
2056     }else if (dim >4) {
2057       *norm2 /= norm;
2058       *norm3 /= norm;
2059       for (k= dim-4, colp= normal+4; k--; )
2060         *colp++ /= norm;
2061     }
2062   }else if (norm == 0.0) {
2063     temp= sqrt (1.0/dim);
2064     for (k= dim, colp= normal; k--; )
2065       *colp++ = temp;
2066   }else {
2067     if (!toporient)
2068       norm= -norm;
2069     for (k= dim, colp= normal; k--; colp++) { /* k used below */
2070       temp= qh_divzero (*colp, norm, qh MINdenom_1, &zerodiv);
2071       if (!zerodiv)
2072 	*colp= temp;
2073       else {
2074 	maxp= qh_maxabsval(normal, dim);
2075 	temp= ((*maxp * norm >= 0.0) ? 1.0 : -1.0);
2076 	for (k= dim, colp= normal; k--; colp++)
2077 	  *colp= 0.0;
2078 	*maxp= temp;
2079 	zzinc_(Znearlysingular);
2080 	trace0((qh ferr, "qh_normalize: norm=%2.2g too small\n", norm));
2081 	return;
2082       }
2083     }
2084   }
2085 } /* normalize */
2086 
2087 
2088 /*-------------------------------------------
2089 -orientoutside- make facet outside oriented via qh interior_point
2090   returns True if reversed orientation.
2091 */
qh_orientoutside(facetT * facet)2092 boolT qh_orientoutside (facetT *facet) {
2093   int k;
2094   realT dist;
2095 
2096   qh_distplane (qh interior_point, facet, &dist);
2097   if (dist > 0) {
2098     for (k= qh hull_dim; k--; )
2099       facet->normal[k]= -facet->normal[k];
2100     facet->offset= -facet->offset;
2101     return True;
2102   }
2103   return False;
2104 } /* orientoutside */
2105 
2106 /*-------------------------------------------
2107 -pointdist- distance between points
2108 */
qh_pointdist(pointT * point1,pointT * point2,int dim)2109 coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
2110   coordT dist, diff;
2111   int k;
2112 
2113   dist= 0.0;
2114   for (k= dim; k--; ) {
2115     diff= *point1++ - *point2++;
2116     dist += diff * diff;
2117   }
2118   return(sqrt(dist));
2119 } /* pointdist */
2120 
2121 
2122 /*-------------------------------------------------
2123 -printmatrix- print matrix given by row vectors
2124   print a vector by (fp, "", &vect, 1, len)
2125 */
qh_printmatrix(FILE * fp,const char * string,realT ** rows,int numrow,int numcol)2126 void qh_printmatrix (FILE *fp, const char *string, realT **rows, int numrow, int numcol) {
2127   realT *rowp;
2128   int i,k;
2129 
2130   fprintf (fp, "%s\n", string);
2131   for (i= 0; i<numrow; i++) {
2132     rowp= rows[i];
2133     for (k= 0; k<numcol; k++)
2134       fprintf (fp, "%6.3g ", *rowp++);
2135     fprintf (fp, "\n");
2136   }
2137 } /* printmatrix */
2138 
2139 
2140 /*-------------------------------------------------
2141 -printpoints- print pointids for a set of points starting at index
2142   prints string and 'p' if defined
2143 */
qh_printpoints(FILE * fp,const char * string,setT * points)2144 void qh_printpoints (FILE *fp, const char *string, setT *points) {
2145   pointT *point, **pointp;
2146 
2147   if (string) {
2148     fprintf (fp, "%s", string);
2149     FOREACHpoint_(points)
2150       fprintf (fp, " p%d", qh_pointid(point));
2151     fprintf (fp, "\n");
2152   }else {
2153     FOREACHpoint_(points)
2154       fprintf (fp, " %d", qh_pointid(point));
2155     fprintf (fp, "\n");
2156   }
2157 } /* printpoints */
2158 
2159 
2160 /*-------------------------------------------------
2161 -projectinput- project input points using qh DELAUNAY and qh low_bound/high_bound
2162   input points in qh first_point, num_points, input_dim
2163      if POINTSmalloc, will free old point array
2164   if low[k]=high[k]= 0, removes dimension k
2165      checks that hull_dim agrees with input_dim, PROJECTinput, and DELAUNAY
2166   if DELAUNAY
2167     projects points to paraboloid
2168 returns:
2169   new point array in first_point of qh hull_dim coordinates
2170   sets POINTSmalloc
2171   lowbound/highbound is also projected
2172 */
qh_projectinput(void)2173 void qh_projectinput (void) {
2174   int k,i;
2175   int newdim= qh input_dim, newnum= qh num_points;
2176   signed char *project;
2177   int size= (qh input_dim+1)*sizeof(*project);
2178   pointT *newpoints, *coord, *infinity;
2179   realT paraboloid, maxboloid= 0;
2180 
2181   project= (signed char *)qh_memalloc (size);
2182   memset ((char*)project, 0, size);
2183   for (k= 0; k<qh input_dim; k++) {   /* skip Delaunay bound */
2184     if (qh lower_bound[k] == 0 && qh upper_bound[k] == 0) {
2185       project[k]= -1;
2186       newdim--;
2187     }
2188   }
2189   if (qh DELAUNAY) {
2190     project[k]= 1;
2191     newdim++;
2192     newnum++;
2193   }
2194   if (newdim != qh hull_dim) qhull_fatal(26);
2195 
2196   if (!(newpoints=(coordT*)malloc(newnum*newdim*sizeof(coordT))))
2197     qhull_fatal(27);
2198 
2199   qh_projectpoints (project, qh input_dim+1, qh first_point,
2200                     qh num_points, qh input_dim, newpoints, newdim);
2201   trace1((qh ferr, "qh_projectinput: updating lower and upper_bound\n"));
2202   qh_projectpoints (project, qh input_dim+1, qh lower_bound,
2203                     1, qh input_dim+1, qh lower_bound, newdim+1);
2204   qh_projectpoints (project, qh input_dim+1, qh upper_bound,
2205                     1, qh input_dim+1, qh upper_bound, newdim+1);
2206   qh_memfree(project, ((qh input_dim+1)*sizeof(*project)));
2207   if (qh POINTSmalloc)
2208     free (qh first_point);
2209   qh first_point= newpoints;
2210   qh POINTSmalloc= True;
2211   if (qh DELAUNAY) {
2212     coord= qh first_point;
2213     infinity= qh first_point + qh hull_dim * qh num_points;
2214     for (k=qh hull_dim-1; k--; )
2215       infinity[k]= 0.0;
2216     for (i=qh num_points; i--; ) {
2217       paraboloid= 0.0;
2218       for (k=qh hull_dim-1; k--; ) {
2219         paraboloid += *coord * *coord;
2220 	infinity[k] += *coord;
2221         coord++;
2222       }
2223       *(coord++)= paraboloid;
2224       maximize_(maxboloid, paraboloid);
2225     }
2226     for (k=qh hull_dim-1; k--; )
2227       *(coord++) /= qh num_points;
2228     *(coord++)= maxboloid * 1.1;
2229     qh num_points++;
2230     trace0((qh ferr, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
2231   }
2232 } /* projectinput */
2233 
2234 
2235 /*-------------------------------------------------
2236 -projectpoint- project point onto a facet by dist
2237   projects point to hyperplane if dist= distplane(point,facet)
2238 returns:
2239   returns a new point
2240   assumes normal_size is in short memory
2241 */
2242 
qh_projectpoint(pointT * point,facetT * facet,realT dist)2243 pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist) {
2244   pointT *newpoint, *np, *normal;
2245   int normsize= qh normal_size,k;
2246   void **freelistp;
2247 
2248   float_qh_memalloc_(normsize, freelistp, newpoint);
2249   np= newpoint;
2250   normal= facet->normal;
2251   for(k= qh hull_dim; k--; )
2252     *(np++)= *point++ - dist * *normal++;
2253   return(newpoint);
2254 } /* projectpoint */
2255 
2256 
2257 /*-------------------------------------------------
2258 -projectpoints- project along one or more dimensions
2259   delete dimension k if project[k] == -1
2260   add dimension k if project[k] == 1
2261   n is size of project
2262   points, numpoints, dim is old points
2263   newpoints, newdim is buffer for new points (already allocated)
2264     newpoints may be points if only adding dimension at end
2265 */
qh_projectpoints(signed char * project,int n,realT * points,int numpoints,int dim,realT * newpoints,int newdim)2266 void qh_projectpoints (signed char *project, int n, realT *points,
2267         int numpoints, int dim, realT *newpoints, int newdim) {
2268   int testdim= dim, oldk=0, newk=0, i,j=0,k;
2269   realT *newp, *oldp;
2270 
2271   for (k= 0; k<n; k++)
2272     testdim += project[k];
2273   if (testdim != newdim) qhull_fatal(28);
2274 
2275   for (j= 0; j<n; j++) {
2276     if (project[j] == -1)
2277       oldk++;
2278     else {
2279       newp= newpoints+newk++;
2280       if (project[j] == +1) {
2281 	if (oldk >= dim)
2282 	  continue;
2283 	oldp= points+oldk;
2284       }else
2285 	oldp= points+oldk++;
2286       for (i=numpoints; i--; ) {
2287         *newp= *oldp;
2288         newp += newdim;
2289         oldp += dim;
2290       }
2291     }
2292     if (oldk >= dim)
2293       break;
2294   }
2295   trace1((qh ferr, "qh_projectpoints: projected %d points from dim %d to dim %d\n",
2296     numpoints, dim, newdim));
2297 } /* projectpoints */
2298 
2299 
2300 /*-------------------------------------------------
2301 -randomfactor- return a random factor within qh RANDOMmax of 1.0
2302   RANDOMa/b definedin global.c
2303 */
qh_randomfactor(void)2304 realT qh_randomfactor (void) {
2305   realT randr;
2306 
2307   randr= qh_RANDOMint;
2308   return randr * qh RANDOMa + qh RANDOMb;
2309 } /* randomfactor */
2310 
2311 /*-------------------------------------------------
2312 -randommatrix- generate a random dimXdim matrix in range (-1,1)
2313   assumes buffer is dim+1Xdim
2314 returns:
2315   returns row vector for buffer
2316   plus row[dim] for scratch
2317 */
qh_randommatrix(realT * buffer,int dim,realT ** row)2318 void qh_randommatrix (realT *buffer, int dim, realT **row) {
2319   int i, k;
2320   realT **rowi, *coord, realr;
2321 
2322   coord= buffer;
2323   rowi= row;
2324   for (i=0; i<dim; i++) {
2325     *(rowi++)= coord;
2326     for (k=0; k<dim; k++) {
2327       realr= qh_RANDOMint;
2328       *(coord++)= 2.0 * realr/(qh_RANDOMmax+1.0) - 1.0;
2329     }
2330   }
2331   *rowi= coord;
2332 } /* randommatrix */
2333 
2334 
2335 /*-------------------------------------------------
2336 -rotateinput- rotate input using row matrix
2337   input points given by qh first_point, num_points, hull_dim
2338   if qh POINTSmalloc, overwrites input points, else mallocs a new array
2339   assumes rows[dim] is a scratch buffer
2340 returns:
2341   sets qh POINTSmalloc
2342 */
qh_rotateinput(realT ** rows)2343 void qh_rotateinput (realT **rows) {
2344   int size;
2345   pointT *newpoints;
2346 
2347   if (!qh POINTSmalloc) {
2348     size= qh num_points*qh hull_dim*sizeof(pointT);
2349     if (!(newpoints=(coordT*)malloc(size))) qhull_fatal(29);
2350 
2351     memcpy ((char *)newpoints, (char *)qh first_point, size);
2352     qh first_point= newpoints;
2353     qh POINTSmalloc= True;
2354   }
2355   qh_rotatepoints (qh first_point, qh num_points, qh hull_dim, rows);
2356 }  /* rotateinput */
2357 
2358 /*-------------------------------------------------
2359 -rotatepoints- rotate numpoints points by a row matrix
2360   assumes rows[dim] is a scratch buffer
2361 */
qh_rotatepoints(realT * points,int numpoints,int dim,realT ** row)2362 void qh_rotatepoints (realT *points, int numpoints, int dim, realT **row) {
2363   realT *point, *rowi, *coord= NULL, sum, *newval;
2364   int i,j,k;
2365 
2366   for (point= points, j= numpoints; j--; point += dim) {
2367     newval= row[dim];
2368     for (i= 0; i<dim; i++) {
2369       rowi= row[i];
2370       coord= point;
2371       for (sum= 0.0, k= dim; k--; )
2372         sum += *rowi++ * *coord++;
2373       *(newval++)= sum;
2374     }
2375     for (k= dim; k--; )
2376       *(--coord)= *(--newval);
2377   }
2378 } /* rotatepoints */
2379 
2380 
2381 /*-------------------------------------------------
2382 -scaleinput- scale input points using qh low_bound/high_bound
2383   input points given by qh first_point, num_points, hull_dim
2384   if qh POINTSmalloc, overwrites input points, else mallocs a new array
2385 returns:
2386   scales points to low[k], high[k]
2387   sets qh POINTSmalloc
2388 */
qh_scaleinput(void)2389 void qh_scaleinput (void) {
2390   int size;
2391   pointT *newpoints;
2392 
2393   if (!qh POINTSmalloc) {
2394     size= qh num_points*qh hull_dim*sizeof(pointT);
2395 
2396     if (!(newpoints=(coordT*)malloc(size))) qhull_fatal(30);
2397 
2398     memcpy ((char *)newpoints, (char *)qh first_point, size);
2399     qh first_point= newpoints;
2400     qh POINTSmalloc= True;
2401   }
2402   qh_scalepoints (qh first_point, qh num_points, qh hull_dim,
2403        qh lower_bound, qh upper_bound);
2404 }  /* scaleinput */
2405 
2406 /*-------------------------------------------------
2407 -scalepoints- scale points to new lowbound and highbound
2408   retains old bound when newlow= -REALmax or newhigh= +REALmax
2409   overwrites old points
2410 */
qh_scalepoints(pointT * points,int numpoints,int dim,realT * newlows,realT * newhighs)2411 void qh_scalepoints (pointT *points, int numpoints, int dim,
2412 	realT *newlows, realT *newhighs) {
2413   int i,k;
2414   realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
2415   boolT nearzero= False;
2416 
2417   for (k= 0; k<dim; k++) {
2418     newhigh= newhighs[k];
2419     newlow= newlows[k];
2420     if (newhigh > REALmax/2 && newlow < -REALmax/2)
2421       continue;
2422     low= REALmax;
2423     high= -REALmax;
2424     for (i= numpoints, coord= points+k; i--; coord += dim) {
2425       minimize_(low, *coord);
2426       maximize_(high, *coord);
2427     }
2428     if (newhigh > REALmax/2)
2429       newhigh= high;
2430     if (newlow < -REALmax/2)
2431       newlow= low;
2432     scale= qh_divzero (newhigh - newlow, high - low,
2433                   qh MINdenom_1, &nearzero);
2434     if (nearzero) qhull_fatal(31);
2435 
2436     shift= (newlow * high - low * newhigh)/(high-low);
2437     coord= points+k;
2438     for (i= numpoints; i--; coord += dim)
2439       *coord= *coord * scale + shift;
2440     coord= points+k;
2441     if (newlow < newhigh) {
2442       mincoord= newlow;
2443       maxcoord= newhigh;
2444     }else {
2445       mincoord= newhigh;
2446       maxcoord= newlow;
2447     }
2448     for (i= numpoints; i--; coord += dim) {
2449       minimize_(*coord, maxcoord);  /* because of roundoff error */
2450       maximize_(*coord, mincoord);
2451     }
2452     trace0((qh ferr, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n",
2453       k, low, high, newlow, newhigh, numpoints, scale, shift));
2454   }
2455 } /* scalepoints */
2456 
2457 
2458 /*-------------------------------------------------
2459 -setfacetplane- sets the hyperplane for a facet
2460    uses global buffers qh gm_matrix and qh gm_row
2461    overwrites facet->normal if already defined
2462    updates Wnewvertex if PRINTstatistics
2463 */
qh_setfacetplane(facetT * facet)2464 void qh_setfacetplane(facetT *facet) {
2465   pointT *point;
2466   vertexT *vertex, **vertexp;
2467   int k,i=0;
2468   int normsize= qh normal_size;
2469   int oldtrace = 0;
2470   realT dist;
2471   void **freelistp;
2472   coordT *coord, *gmcoord= qh gm_matrix;
2473   pointT *point0= ((vertexT*)SETfirst_(facet->vertices))->point;
2474   boolT nearzero;
2475 
2476   zzinc_(Zsetplane);
2477   if (!facet->normal)
2478     float_qh_memalloc_(normsize, freelistp, facet->normal);
2479   if (facet == qh tracefacet) {
2480     oldtrace= qh IStracing;
2481     qh IStracing= 5;
2482 
2483     /*
2484     fprintf (qh ferr, "qh_setfacetplane: facet f%d created.\n", facet->id);
2485     fprintf (qh ferr, "  Last point added to hull was p%d.", qh furthest_id);
2486     if (zzval_(Ztotmerge))
2487       fprintf(qh ferr, "  Last merge was #%d.", zzval_(Ztotmerge));
2488     fprintf (qh ferr, "\n\nSorry, qh_printsummary no longer supported:\n");
2489        fprintf (qh ferr, "\n\nCurrent summary is:\n");
2490 	  qh_printsummary (qh ferr); */
2491   }
2492   if (qh hull_dim <= 4) {
2493     if (qh RANDOMdist) {
2494       FOREACHvertex_(facet->vertices) {
2495         qh gm_row[i++]= gmcoord;
2496 	coord= vertex->point;
2497 	for (k= qh hull_dim; k--; )
2498 	  *(gmcoord++)= *coord++ * qh_randomfactor();
2499       }
2500     }else {
2501       FOREACHvertex_(facet->vertices)
2502        qh gm_row[i++]= vertex->point;
2503     }
2504     qh_sethyperplane_det(qh hull_dim, qh gm_row, point0,
2505 			 (boolT)facet->toporient,
2506 			 facet->normal, &facet->offset);
2507   }else {
2508     FOREACHvertex_(facet->vertices) {
2509       if (vertex->point != point0) {
2510 	qh gm_row[i++]= gmcoord;
2511 	coord= vertex->point;
2512 	point= point0;
2513 	for(k= qh hull_dim; k--; )
2514 	  *(gmcoord++)= *coord++ - *point++;
2515       }
2516     }
2517     qh gm_row[i]= gmcoord;  /* for areasimplex */
2518     if (qh RANDOMdist) {
2519       gmcoord= qh gm_matrix;
2520       for (i= qh hull_dim-1; i--; ) {
2521 	for (k= qh hull_dim; k--; )
2522 	  *(gmcoord++) *= qh_randomfactor();
2523       }
2524     }
2525     qh_sethyperplane_gauss(qh hull_dim, qh gm_row, point0,
2526 			   (boolT)facet->toporient,
2527 			   facet->normal, &facet->offset, &nearzero);
2528     if (nearzero) {
2529       if (qh_orientoutside (facet)) {
2530 	trace0((qh ferr, "qh_setfacetplane: flipped orientation after testing interior_point\n"));
2531       /* this is part of using Gaussian Elimination.  For example in 5-d
2532 	   1 1 1 1 0
2533 	   1 1 1 1 1
2534 	   0 0 0 1 0
2535 	   0 1 0 0 0
2536 	   1 0 0 0 0
2537 	   norm= 0.38 0.38 -0.76 0.38 0
2538 	 has a determinate of 1, but g.e. after subtracting pt. 0 has
2539 	 0's in the diagonal, even with full pivoting.  It does work
2540 	 if you subtract pt. 4 instead. */
2541       }
2542     }
2543   }
2544   if (qh PRINTstatistics) {
2545     FOREACHvertex_(facet->vertices) {
2546       if (vertex->point != point0) {
2547 	zinc_(Zdiststat);
2548         qh_distplane(vertex->point, facet, &dist);
2549         dist= fabs_(dist);
2550         zinc_(Znewvertex);
2551         wadd_(Wnewvertex, dist);
2552         if (dist > wval_(Wnewvertexmax)) {
2553           wval_(Wnewvertexmax)= dist;
2554           maximize_(qh max_outside, dist);
2555         }
2556       }
2557     }
2558   }
2559 
2560   if (qh IStracing >= 3) {
2561     /*
2562     fprintf (qh ferr, "qh_setfacetplane: f%d offset %2.2g normal: ",
2563 	     facet->id, facet->offset);
2564     for (k=0; k<qh hull_dim; k++)
2565       fprintf (qh ferr, "%2.2g ", facet->normal[k]);
2566     fprintf (qh ferr, "\n");
2567     */
2568   }
2569 
2570   if (facet == qh tracefacet)
2571     qh IStracing= oldtrace;
2572 } /* setfacetplane */
2573 
2574 
2575 /*-------------------------------------------------
2576 -sethyperplane_det- set normalized hyperplane equation from oriented simplex
2577   dim X dim array indexed by rows[], one row per point, point0 is any row
2578   only defined for dim == 2..4
2579 returns:
2580   offset, normal
2581   bumps Znearlysingular if normalization fails
2582   rows[] is not modified
2583 notes:
2584   solves det(P-V_0, V_n-V_0, ..., V_1-V_0)=0, i.e. every point is on hyperplane
2585   offset places point0 on the hyperplane
2586   toporient just flips all signs, so orientation is correct
2587   see Bower & Woodworth, A programmer's geometry, Butterworths 1983.
2588 */
qh_sethyperplane_det(int dim,coordT ** rows,coordT * point0,boolT toporient,coordT * normal,realT * offset)2589 void qh_sethyperplane_det (int dim, coordT **rows, coordT *point0,
2590           boolT toporient, coordT *normal, realT *offset) {
2591 
2592   if (dim == 2) {
2593     normal[0]= dY(1,0);
2594     normal[1]= dX(0,1);
2595     qh_normalize (normal, dim, toporient);
2596     *offset= -(point0[0]*normal[0]+point0[1]*normal[1]);
2597   }else if (dim == 3) {
2598     normal[0]= det2_(dY(2,0), dZ(2,0),
2599 		     dY(1,0), dZ(1,0));
2600     normal[1]= det2_(dX(1,0), dZ(1,0),
2601 		     dX(2,0), dZ(2,0));
2602     normal[2]= det2_(dX(2,0), dY(2,0),
2603 		     dX(1,0), dY(1,0));
2604     qh_normalize (normal, dim, toporient);
2605     *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
2606 	       + point0[2]*normal[2]);
2607   }else if (dim == 4) {
2608     normal[0]= - det3_(dY(2,0), dZ(2,0), dW(2,0),
2609 			dY(1,0), dZ(1,0), dW(1,0),
2610 			dY(3,0), dZ(3,0), dW(3,0));
2611     normal[1]=   det3_(dX(2,0), dZ(2,0), dW(2,0),
2612 		        dX(1,0), dZ(1,0), dW(1,0),
2613 		        dX(3,0), dZ(3,0), dW(3,0));
2614     normal[2]= - det3_(dX(2,0), dY(2,0), dW(2,0),
2615 			dX(1,0), dY(1,0), dW(1,0),
2616 			dX(3,0), dY(3,0), dW(3,0));
2617     normal[3]=   det3_(dX(2,0), dY(2,0), dZ(2,0),
2618 		        dX(1,0), dY(1,0), dZ(1,0),
2619 		        dX(3,0), dY(3,0), dZ(3,0));
2620     qh_normalize (normal, dim, toporient);
2621     *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
2622 	       + point0[2]*normal[2] + point0[3]*normal[3]);
2623   }
2624 } /* sethyperplane_det */
2625 
2626 
2627 /*-------------------------------------------------
2628 -sethyperplane_gauss- set normalized hyperplane equation from oriented simplex
2629     (dim-1) X dim array of rows[i]= V_{i+1} - V_0 (point0)
2630 returns:
2631     offset, normal
2632     if nearzero, bumps Znearlysingular
2633       orientation may be incorrect because of incorrect sign flips in gausselim
2634 notes:
2635     solves [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0 .. 0 1]
2636         or [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0]
2637     i.e., N is normal to the hyperplane, and the unnormalized
2638         distance to [0 .. 1] is either 1 or 0
2639     offset places point0 on the hyperplane
2640 */
qh_sethyperplane_gauss(int dim,coordT ** rows,pointT * point0,boolT toporient,coordT * normal,coordT * offset,boolT * nearzero)2641 void qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0,
2642 		boolT toporient, coordT *normal, coordT *offset, boolT *nearzero) {
2643   coordT *pointcoord, *normalcoef;
2644   int k, tempint;
2645   boolT sign= (boolT)!toporient, nearzero2= False;
2646 
2647   qh_gausselim(rows, dim-1, dim, &sign, nearzero);
2648   for(k= dim-1; k--; ) {
2649     if ((rows[k])[k] < 0) {
2650       tempint = (int)sign;
2651       tempint ^= 1;
2652       sign = (boolT)tempint;
2653     }
2654   }
2655   if (*nearzero) {
2656     zinc_(Znearlysingular);
2657     trace0((qh ferr, "qh_sethyperplane_gauss: nearly singular or axis parallel hyperplane.\n"));
2658     qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
2659   }else {
2660     qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
2661     if (nearzero2) {
2662       zinc_(Znearlysingular);
2663       trace0((qh ferr, "qh_sethyperplane_gauss: singular or axis parallel hyperplane at normalization\n"));
2664     }
2665   }
2666   if (nearzero2)
2667     *nearzero= True;
2668   qh_normalize(normal, dim, True);
2669   pointcoord= point0;
2670   normalcoef= normal;
2671   *offset= -(*pointcoord++ * *normalcoef++);
2672   for(k= dim-1; k--; )
2673     *offset -= *pointcoord++ * *normalcoef++;
2674 } /* sethyperplane_gauss */
2675 
2676 /*-------------------------------------------
2677 -voronoi_center- return Voronoi center for a set of points
2678   dim is the orginal dimension of the points
2679 notes:
2680   if non-simplicial, returns center for max simplex of points
2681   from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65
2682 */
qh_voronoi_center(int dim,setT * points)2683 pointT *qh_voronoi_center (int dim, setT *points) {
2684   pointT *point, **pointp, *point0;
2685   pointT *center= (pointT *)qh_memalloc (qh center_size);
2686   setT *simplex = NULL;
2687   int i, j, k, num, size= qh_setsize(points);
2688   coordT *gmcoord;
2689   realT *diffp, sum2, *sum2row, *sum2p, det, factor;
2690   boolT nearzero, infinite;
2691 
2692   if (size == dim+1)  {
2693     simplex = points;
2694   }
2695   else if (size < dim+1) {
2696     qhull_fatal(32);
2697   }
2698   else {
2699     simplex = qh_settemp (dim+1);
2700     qh_maxsimplex (dim, points, NULL, 0, &simplex);
2701   }
2702   num= qh_setsize (simplex);
2703   point0= (pointT *)SETfirst_(simplex);
2704   gmcoord= qh gm_matrix;
2705   for (k=0; k<dim; k++) {
2706     qh gm_row[k]= gmcoord;
2707     FOREACHpoint_(simplex) {
2708       if (point != point0)
2709         *(gmcoord++)= point[k] - point0[k];
2710     }
2711   }
2712   sum2row= gmcoord;
2713   for (i=0; i<dim; i++) {
2714     sum2= 0.0;
2715     for (k= 0; k<dim; k++) {
2716       diffp= qh gm_row[k] + i;
2717       sum2 += *diffp * *diffp;
2718     }
2719     *(gmcoord++)= sum2;
2720   }
2721   det= qh_determinant (qh gm_row, dim, &nearzero);
2722   factor= qh_divzero (0.5, det, qh MINdenom, &infinite);
2723   if (infinite) {
2724     for (k=dim; k--; )
2725       center[k]= qh_INFINITE;
2726     if (qh IStracing)
2727       qh_printpoints (qh ferr, "qh_voronoi_center: at infinity for ", simplex);
2728   }else {
2729     for (i=0; i<dim; i++) {
2730       gmcoord= qh gm_matrix;
2731       sum2p= sum2row;
2732       for (k=0; k<dim; k++) {
2733 	qh gm_row[k]= gmcoord;
2734 	if (k == i) {
2735 	  for (j= dim; j--; )
2736 	    *(gmcoord++)= *sum2p++;
2737 	}else {
2738 	  FOREACHpoint_(simplex) {
2739 	    if (point != point0)
2740 	      *(gmcoord++)= point[k] - point0[k];
2741 	  }
2742 	}
2743       }
2744       center[i]= qh_determinant (qh gm_row, dim, &nearzero)*factor + point0[i];
2745     }
2746     if (qh IStracing >= 3) {
2747 
2748       /*
2749       fprintf (qh ferr, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
2750       qh_printmatrix (qh ferr, "center:", &center, 1, dim);
2751       if (qh IStracing >= 5) {
2752 	qh_printpoints (qh ferr, "points", simplex);
2753 	FOREACHpoint_(simplex)
2754 	  fprintf (qh ferr, "p%d dist %.2g, ", qh_pointid (point),
2755 		   qh_pointdist (point, center, dim));
2756 	fprintf (qh ferr, "\n");
2757       }
2758       */
2759 
2760     }
2761   }
2762   if (simplex != points)
2763     qh_settempfree (&simplex);
2764   return center;
2765 } /* voronoi_center */
2766 
2767 
2768 /*************************************************************************/
2769 /****************** implementation code from stat.c **********************/
2770 /*************************************************************************/
2771 
2772 /* stat.c - contains all statistics that are collected for qhull
2773 
2774    see README and stat.h
2775 
2776    copyright (c) 1993-1994, The Geometry Center
2777 */
2778 
2779 #if qh_QHpointer
2780 qhstatT *qh_qhstat=NULL;  /* global data structure */
2781 #else
2782 qhstatT qh_qhstat;   /* remove "={0}" if this causes a compiler error */
2783 #endif
2784 
2785 
2786 /*-------------------------------------------------
2787 -allstatA -- define statistics in groups of 20
2788   (otherwise, 'gcc -O2' uses too much memory)
2789   uses qhstat next
2790 */
qh_allstatA(void)2791 void qh_allstatA (void) {
2792 
2793    /* zdef_(type,name,doc,average) */
2794   zzdef_(zdoc, Zdoc2, "precision statistics", -1);
2795   zdef_(zinc, Znewvertex, static_cast<const char *>(NULL), -1);
2796   zdef_(wadd, Wnewvertex, "ave. distance of a new vertex to a facet (not 0s)", Znewvertex);
2797   zdef_(wmax, Wnewvertexmax, "max. distance of a new vertex to a facet", -1);
2798   zdef_(wmax, Wvertexmax, "max. distance of an output vertex to a facet", -1);
2799   zdef_(wmin, Wvertexmin, "min. distance of an output vertex to a facet", -1);
2800   zdef_(wmin, Wmindenom, "min. denominator in hyperplane computation", -1);
2801 
2802   qhstat precision= qhstat next;
2803   zzdef_(zdoc, Zdoc3, "precision problems", -1);
2804   zzdef_(zinc, Zcoplanarridges, "coplanar half ridges in output", -1);
2805   zzdef_(zinc, Zconcaveridges, "concave half ridges in output", -1);
2806   zzdef_(zinc, Zflippedfacets, "flipped facets", -1);
2807   zzdef_(zinc, Zcoplanarhorizon, "coplanar horizon facets for new vertices", -1);
2808   zzdef_(zinc, Zcoplanarpart, "coplanar points during partitioning", -1);
2809   zzdef_(zinc, Znearlysingular, "nearly singular or axis-parallel hyperplanes", -1);
2810   zzdef_(zinc, Zback0, "zero divisors during back substitute", -1);
2811   zzdef_(zinc, Zgauss0, "zero divisors during gaussian elimination", -1);
2812   zzdef_(zinc, Zmultimatch, "ridges with multiple neighbors (same flip)", -1);
2813   zzdef_(zinc, Zmultiflip, "ridges with multiple neighbors (diff flip)", -1);
2814 
2815 }
qh_allstatB(void)2816 void qh_allstatB (void) {
2817   zzdef_(zdoc, Zdoc1, "summary information", -1);
2818   zdef_(zinc, Zvertices, "number of vertices in output", -1);
2819   zdef_(zinc, Znumfacets, "number of facets in output", -1);
2820   zdef_(zinc, Znumridges, "number of ridges in output", -1);
2821   zdef_(zadd, Znumridges, "average number of ridges per facet", Znumfacets);
2822   zdef_(zmax, Zmaxridges, "maximum number of ridges", -1);
2823   zdef_(zadd, Znumneighbors, "average number of neighbors per facet", Znumfacets);
2824   zdef_(zmax, Zmaxneighbors, "maximum number of neighbors", -1);
2825   zdef_(zadd, Znumvertices, "average number of vertices per facet", Znumfacets);
2826   zdef_(zmax, Zmaxvertices, "maximum number of vertices", -1);
2827   zdef_(zadd, Znumvneighbors, "average number of neighbors per vertex", Zvertices);
2828   zdef_(zmax, Zmaxvneighbors, "maximum number of neighbors", -1);
2829   zdef_(wadd, Wcpu, "cpu seconds for qhull after input", -1);
2830   zdef_(zinc, Ztotvertices, "vertices created altogether", -1);
2831   zzdef_(zinc, Zsetplane, "facets created altogether", -1);
2832   zdef_(zinc, Ztotridges, "ridges created altogether", -1);
2833   zdef_(zinc, Zpostfacets, "facets before post merge", -1);
2834   zdef_(zinc, Zangle, static_cast<const char *>(NULL), -1);
2835   zdef_(wadd, Wangle, "average angle (cosine) for all ridges", Zangle);
2836   zdef_(wmax, Wanglemax, "maximum angle (cosine) of a ridge", -1);
2837   zdef_(wmin, Wanglemin, "minimum angle (cosine) of a ridge", -1);
2838 
2839 
2840   zdef_(zdoc, Zdoc9, "build hull statistics", -1);
2841   zdef_(zinc, Zdetsimplex, "determinates computed (initial hull)", -1);
2842   zzdef_(zinc, Zprocessed, "points processed", -1);
2843   zdef_(zinc, Ztotvisible, "visible facets for all new vertices", -1);
2844   zdef_(zinc, Zinsidevisible, "visible facets without an horizon neighbor", -1);
2845   zdef_(zinc, Ztothorizon, "horizon facets for all new vertices", -1);
2846   zdef_(wadd, Wnewbalance, "average new facet balance", Zprocessed);
2847   zdef_(wadd, Wnewbalance2, "  standard deviation", -1);
2848   zdef_(wadd, Wpbalance, "average partition balance", Zpbalance);
2849   zdef_(wadd, Wpbalance2, "  standard deviation", -1);
2850   zdef_(zinc, Zsearchpoints, "searches of all points for initial simplex", -1);
2851   zdef_(zinc, Znotmax, "points ignored (not above max_outside)", -1);
2852   zdef_(zinc, Znotgood, "points ignored (not above a good facet)", -1);
2853   zdef_(zinc, Znotgoodnew, "points ignored (didn't create a good new facet)", -1);
2854   zdef_(zinc, Zgoodfacet, "good facets found", -1);
2855   zzdef_(zinc, Znumvisibility, "distance tests for facet visibility", -1);
2856   zdef_(zinc, Ztotverify, "points verified", -1);
2857   zdef_(zinc, Zverifypart, "  ave. distance tests per verify", Ztotverify);
2858 }
qh_allstatC(void)2859 void qh_allstatC(void) {
2860   zdef_(zdoc, Zdoc4, "partitioning statistics", -1);
2861   zdef_(zinc, Zpartinside, "inside points", -1);
2862   zdef_(zinc, Zcoplanarinside, "  inside points that were coplanar with a facet", -1);
2863   zdef_(zinc, Ztotpartition, "partitions of a point", -1);
2864 
2865   zzdef_(zinc, Zpartitionall, "distance tests for initial partition", -1);
2866   zzdef_(zinc, Zpartition, "distance tests for other partitions", -1);
2867   zdef_(zinc, Zpartneighbor, "extra distance tests for coplanar and flipped neighbors", -1);
2868   zzdef_(zinc, Zdistcheck, "distance tests for checking flipped facets", -1);
2869   zzdef_(zinc, Zdistconvex, "distance tests for checking convexity", -1);
2870   zdef_(zinc, Zdistgood, "distance tests for checking good point", -1);
2871   zdef_(zinc, Zdistio, "distance tests for output", -1);
2872   zdef_(zinc, Zdiststat, "distance tests for statistics", -1);
2873   zdef_(zinc, Zdistplane, "total number of distance tests", -1);
2874   zdef_(zinc, Ztotpartcoplanar, "partitions of coplanar points or deleted vertices", -1);
2875   zzdef_(zinc, Zpartcoplanar, "   distance tests for these partitions", -1);
2876   zdef_(zinc, Zcomputefurthest, "distance tests for computing furthest", -1);
2877 
2878 }
qh_allstatD(void)2879 void qh_allstatD(void) {
2880   zdef_(zdoc, Zdoc5, "statistics for matching ridges", -1);
2881   zdef_(zinc, Zhashlookup, "total lookups for matching ridges of new facets", -1);
2882   zdef_(zinc, Zhashtests, "average number of tests to match a ridge", Zhashlookup);
2883   zdef_(zinc, Zhashridge, "total lookups of subridges (duplicates and boundary)", -1);
2884   zdef_(zinc, Zhashridgetest, "average number of tests per subridge", Zhashridge);
2885 
2886   zdef_(zdoc, Zdoc6, "statistics for determining merges", -1);
2887   zdef_(zinc, Zangletests, "angles computed for ridge convexity", -1);
2888   zdef_(zinc, Zbestcentrum, "best merges used centrum instead of vertices", -1);
2889   zzdef_(zinc, Zbestdist, "distance tests for best merge", -1);
2890   zzdef_(zinc, Zcentrumtests, "distance tests for centrum convexity", -1);
2891   zdef_(zinc, Zcoplanarangle, "coplanar angles in getmergeset", -1);
2892   zdef_(zinc, Zcoplanarcentrum, "coplanar centrums in getmergeset", -1);
2893   zdef_(zinc, Zconcaveridge, "concave ridges in getmergeset", -1);
2894 }
qh_allstatE(void)2895 void qh_allstatE(void) {
2896   zdef_(zdoc, Zdoc7, "statistics for merging", -1);
2897   zdef_(wmax, Wmaxoutside, "max distance of merged vertex above facet", -1);
2898   zdef_(wmin, Wminvertex, "max distance of merged vertex below facet", -1);
2899   zzdef_(zinc, Ztotmerge, "total number of facets merged", -1);
2900   zdef_(zinc, Zmergenew, "new facets merged", -1);
2901   zdef_(zinc, Zmergehorizon, "horizon facets merged into new facets", -1);
2902   zdef_(zinc, Zmergeintohorizon, "new facets merged into horizon", -1);
2903   zdef_(zinc, Zmergevertex, "vertices deleted by merging", -1);
2904   zdef_(zinc, Zdegenvertex, "vertices deleted by degenerate facet", -1);
2905   zdef_(zinc, Zmergeflip, "merges due to flipped neighbors", -1);
2906   zdef_(zinc, Zmergeflipdup, "merges due to flipped facets in duplicated ridge", -1);
2907   zdef_(zinc, Zneighbor, "merges due to redundant neighbors", -1);
2908   zdef_(zinc, Zacoplanar, "merges due to angle coplanar facets", -1);
2909   zdef_(wadd, Wacoplanartot, "  average merge distance", Zacoplanar);
2910   zdef_(wmax, Wacoplanarmax, "  maximum merge distance", -1);
2911   zdef_(zinc, Zcoplanar, "merges due to coplanar facets", -1);
2912   zdef_(wadd, Wcoplanartot, "  average merge distance", Zcoplanar);
2913   zdef_(wmax, Wcoplanarmax, "  maximum merge distance", -1);
2914   zdef_(zinc, Zconcave, "merges due to concave facets", -1);
2915   zdef_(wadd, Wconcavetot, "  average merge distance", Zconcave);
2916   zdef_(wmax, Wconcavemax, "  maximum merge distance", -1);
2917   zdef_(zinc, Zavoidold, "coplanar/concave merges due to avoiding old merge", -1);
2918   zdef_(wadd, Wavoidoldtot, "  average merge distance", Zavoidold);
2919   zdef_(wmax, Wavoidoldmax, "  maximum merge distance", -1);
2920   zdef_(zinc, Zdegen, "merges due to degenerate facets", -1);
2921   zdef_(wadd, Wdegentot, "  average merge distance", Zdegen);
2922   zdef_(wmax, Wdegenmax, "  maximum merge distance", -1);
2923   zdef_(zinc, Zflipped, "merges due to removing flipped facets", -1);
2924   zdef_(wadd, Wflippedtot, "  average merge distance", Zflipped);
2925   zdef_(wmax, Wflippedmax, "  maximum merge distance", -1);
2926   zdef_(zinc, Zduplicate, "merges due to duplicated ridges", -1);
2927   zdef_(wadd, Wduplicatetot, "  average merge distance", Zduplicate);
2928   zdef_(wmax, Wduplicatemax, "  maximum merge distance", -1);
2929 
2930 }
qh_allstatF(void)2931 void qh_allstatF(void) {
2932   zdef_(zdoc, Zdoc8, "renamed vertex statistics", -1);
2933   zdef_(zinc, Zrenameshare, "renamed vertices shared by two facets", -1);
2934   zdef_(zinc, Zrenamepinch, "renamed vertices in a pinched facet", -1);
2935   zdef_(zinc, Zrenameall, "renamed vertices shared by multiple facets", -1);
2936   zdef_(zinc, Zfindfail, "rename failures due to duplicated ridges", -1);
2937   zdef_(zinc, Zdupridge, "  duplicate ridges detected", -1);
2938   zdef_(zinc, Zdelridge, "deleted ridges due to renamed vertices", -1);
2939   zdef_(zinc, Zdropneighbor, "dropped neighbors due to renamed vertices", -1);
2940   zdef_(zinc, Zdropdegen, "degenerate facets due to dropped neighbors", -1);
2941   zdef_(zinc, Zdelfacetdup, "  facets deleted because of no neighbors", -1);
2942   zdef_(zinc, Zremvertex, "vertices removed from facets due to no ridges", -1);
2943   zdef_(zinc, Zremvertexdel, "vertices deleted due to no ridges", -1);
2944   zdef_(zinc, Zintersectnum, "vertex intersections for locating redundant vertices", -1);
2945   zdef_(zinc, Zintersectfail, "intersections failed to find a redundant vertex", -1);
2946   zdef_(zinc, Zintersect, "intersections found redundant vertices", -1);
2947   zdef_(zadd, Zintersecttot, "   ave. number found per vertex", Zintersect);
2948   zdef_(zmax, Zintersectmax, "   max. found for a vertex", -1);
2949   zdef_(zinc, Zvertexridge, static_cast<const char *>(NULL), -1);
2950   zdef_(zadd, Zvertexridgetot, "  ave. number of ridges per tested vertex", Zvertexridge);
2951   zdef_(zmax, Zvertexridgemax, "  max. number of ridges per tested vertex", -1);
2952 
2953   zdef_(zdoc, Zdoc10, "memory usage statistics (in bytes)", -1);
2954   zdef_(zadd, Zmemfacets, "for facets and their normals, neighbor and vertex sets", -1);
2955   zdef_(zadd, Zmemvertices, "for vertices and their neighbor sets", -1);
2956   zdef_(zadd, Zmempoints, "for input points and outside and coplanar sets",-1);
2957   zdef_(zadd, Zmemridges, "for ridges and their vertex sets", -1);
2958 } /* allstat */
2959 
2960 
2961 #if qh_KEEPstatistics
2962 /*-------------------------------------------------
2963 -collectstatistics- collect statistics for qh facet_list
2964 */
qh_collectstatistics(void)2965 void qh_collectstatistics (void) {
2966   facetT *facet, *neighbor, **neighborp;
2967   vertexT *vertex, **vertexp;
2968   realT dotproduct, dist;
2969   int sizneighbors, sizridges, sizvertices;
2970 
2971   zval_(Zmempoints)= qh num_points * qh normal_size +
2972                              sizeof (qhT) + sizeof (qhstatT);
2973   zval_(Zmemfacets)= 0;
2974   zval_(Zmemridges)= 0;
2975   zval_(Zmemvertices)= 0;
2976   zval_(Zangle)= 0;
2977   wval_(Wangle)= 0.0;
2978   zval_(Znumridges)= 0;
2979   zval_(Znumfacets)= 0;
2980   zval_(Znumneighbors)= 0;
2981   zval_(Znumvertices)= 0;
2982   zval_(Znumvneighbors)= 0;
2983   zval_(Zvertices)= qh num_vertices - qh_setsize (qh del_vertices);
2984   if (qh MERGING || qh APPROXhull)
2985     wmax_(Wmaxoutside, qh max_outside);
2986   if (qh MERGING)
2987     wmin_(Wminvertex, qh min_vertex);
2988   FORALLfacets
2989     facet->seen= False;
2990   if (qh DELAUNAY) {
2991     FORALLfacets {
2992       if (facet->normal && facet->normal[qh hull_dim - 1] > 0.0)
2993         facet->seen= True;
2994     }
2995   }
2996   FORALLfacets {
2997     if (facet->visible && qh NEWfacets)
2998       continue;
2999     sizvertices= qh_setsize (facet->vertices);
3000     sizneighbors= qh_setsize (facet->neighbors);
3001     sizridges= qh_setsize (facet->ridges);
3002     zinc_(Znumfacets);
3003     zadd_(Znumvertices, sizvertices);
3004     zmax_(Zmaxvertices, sizvertices);
3005     zadd_(Znumneighbors, sizneighbors);
3006     zmax_(Zmaxneighbors, sizneighbors);
3007     if (sizridges) {
3008       zadd_(Znumridges, sizridges);
3009       zmax_(Zmaxridges, sizridges);
3010     }
3011     zadd_(Zmemfacets, sizeof (facetT) + qh normal_size + 2*sizeof (setT)
3012        + SETelemsize * (sizneighbors + sizvertices));
3013     if (facet->ridges) {
3014       zadd_(Zmemridges,
3015 	 sizeof (setT) + SETelemsize * sizridges + sizridges *
3016          (sizeof (ridgeT) + sizeof (setT) + SETelemsize * (qh hull_dim-1))/2);
3017     }
3018     if (facet->outsideset)
3019       zadd_(Zmempoints, sizeof (setT) + SETelemsize * qh_setsize (facet->outsideset));
3020     if (facet->coplanarset)
3021       zadd_(Zmempoints, sizeof (setT) + SETelemsize * qh_setsize (facet->coplanarset));
3022     if (facet->seen) /* Delaunay upper envelope */
3023       continue;
3024     facet->seen= True;
3025     FOREACHneighbor_(facet) {
3026       if (neighbor == qh_DUPLICATEridge || neighbor == qh_MERGEridge
3027 	  || neighbor->seen || !facet->normal || !neighbor->normal)
3028 	continue;
3029       dotproduct= qh_getangle(facet->normal, neighbor->normal);
3030       zinc_(Zangle);
3031       wadd_(Wangle, dotproduct);
3032       wmax_(Wanglemax, dotproduct)
3033       wmin_(Wanglemin, dotproduct)
3034     }
3035     FOREACHvertex_(facet->vertices) {
3036       zinc_(Zdiststat);
3037       qh_distplane(vertex->point, facet, &dist);
3038       wmax_(Wvertexmax, dist);
3039       wmin_(Wvertexmin, dist);
3040     }
3041   }
3042   FORALLvertices {
3043     if (vertex->deleted)
3044       continue;
3045     zadd_(Zmemvertices, sizeof (vertexT));
3046     if (vertex->neighbors) {
3047       sizneighbors= qh_setsize (vertex->neighbors);
3048       zadd_(Znumvneighbors, sizneighbors);
3049       zmax_(Zmaxvneighbors, sizneighbors);
3050       zadd_(Zmemvertices, sizeof (vertexT) + SETelemsize * sizneighbors);
3051     }
3052   }
3053 } /* collectstatistics */
3054 #endif /* qh_KEEPstatistics */
3055 
3056 /*-------------------------------------------------
3057 -freestatistics- free memory used for statistics
3058 */
qh_freestatistics(void)3059 void qh_freestatistics (void) {
3060 
3061 #if qh_QHpointer   /* duplicated if !KEEPstatistics */
3062   free (qh_qhstat);
3063   qh_qhstat= NULL;
3064 #endif
3065 } /* freestatistics */
3066 
3067 /*-------------------------------------------------
3068 -initstatistics- allocate and initialize statistics
3069   uses malloc instead of memalloc since mem.c not setup yet
3070 */
qh_initstatistics(void)3071 void qh_initstatistics (void) {
3072   int i;
3073   realT realx;
3074   int intx;
3075 
3076 #if qh_QHpointer   /* duplicated if !KEEPstatistics */
3077   if (!(qh_qhstat= (qhstatT *)malloc (sizeof(qhstatT)))) qhull_fatal(33);
3078 #endif
3079 
3080   qhstat next= 0;
3081   qh_allstatA();
3082   qh_allstatB();
3083   qh_allstatC();
3084   qh_allstatD();
3085   qh_allstatE();
3086   qh_allstatF();
3087 
3088   qhstat init[zinc].i= 0;
3089   qhstat init[zadd].i= 0;
3090   qhstat init[zmin].i= INT_MAX;
3091   qhstat init[zmax].i= INT_MIN;
3092   qhstat init[wadd].r= 0;
3093   qhstat init[wmin].r= REALmax;
3094   qhstat init[wmax].r= -REALmax;
3095   for (i=0; i<ZEND; i++) {
3096     if (qhstat type[i] > ZTYPEreal) {
3097       realx= qhstat init[(unsigned char)(qhstat type[i])].r;
3098       qhstat stats[i].r= realx;
3099     }else if (qhstat type[i] != zdoc) {
3100       intx= qhstat init[(unsigned char)(qhstat type[i])].i;
3101       qhstat stats[i].i= intx;
3102     }
3103   }
3104 } /* initstatistics */
3105 
3106 /*-------------------------------------------
3107 -newstats- returns True if statistics for zdoc
3108 returns:
3109   next zdoc
3110 */
qh_newstats(int index,int * nextindex)3111 boolT qh_newstats (int index, int *nextindex) {
3112   boolT isnew= False;
3113   int start, i;
3114 
3115   if (qhstat type[qhstat id[index]] == zdoc)
3116     start= index+1;
3117   else
3118     start= index;
3119   for (i= start; i < qhstat next && qhstat type[qhstat id[i]] != zdoc; i++) {
3120     if (!qh_nostatistic(qhstat id[i]) && !qhstat printed[qhstat id[i]])
3121 	isnew= True;
3122   }
3123   *nextindex= i;
3124   return isnew;
3125 } /* newstats */
3126 
3127 /*-------------------------------------------
3128 -nostatistic- true if no statistic to print
3129 */
qh_nostatistic(int i)3130 boolT qh_nostatistic (int i) {
3131 
3132   if ((qhstat type[i] > ZTYPEreal
3133        &&qhstat stats[i].r == qhstat init[(unsigned char)(qhstat type[i])].r)
3134       || (qhstat type[i] < ZTYPEreal
3135 	  &&qhstat stats[i].i == qhstat init[(unsigned char)(qhstat type[i])].i))
3136     return True;
3137   return False;
3138 } /* nostatistic */
3139 
3140 #if qh_KEEPstatistics
3141 /*-------------------------------------------
3142 -qh_printallstatistics- print all statistics to a file
3143 */
qh_printallstatistics(FILE * fp,const char * string)3144 void qh_printallstatistics (FILE *fp, const char *string) {
3145   int i;
3146 
3147   for (i=ZEND; i--; )
3148     qhstat printed[i]= False;
3149   qh_printstatistics (fp, string);
3150 }
3151 
3152 
3153 /*-------------------------------------------
3154 -printstatistics- print statistics to a file
3155 */
qh_printstatistics(FILE * fp,const char * string)3156 void qh_printstatistics (FILE *fp, const char *string) {
3157   int i, k;
3158   realT ave;
3159 
3160   if (qh num_points != qh num_vertices) {
3161     wval_(Wpbalance)= 0;
3162     wval_(Wpbalance2)= 0;
3163   }else
3164     wval_(Wpbalance2)= qh_stddev (zval_(Zpbalance), wval_(Wpbalance),
3165                                  wval_(Wpbalance2), &ave);
3166   wval_(Wnewbalance2)= qh_stddev (zval_(Zprocessed), wval_(Wnewbalance),
3167                                  wval_(Wnewbalance2), &ave);
3168   fprintf (fp, "\n\
3169 %s\n\
3170  qhull invoked by: %s | %s\n", string, qh rbox_command, qh qhull_command);
3171   fprintf (fp, "\nprecision constants:\n\
3172  %6.2g max. coordinate in the input\n\
3173  %6.2g max. roundoff error for distance computation\n\
3174  %6.2g min. distance for outside points\n",
3175               qh maxmaxcoord, qh DISTround, qh MINoutside);
3176   if (qh premerge_cos < REALmax/2) fprintf (fp, "\
3177  %6.2g max. cosine for pre-merge angle\n", qh premerge_cos);
3178   if (qh PREmerge) fprintf (fp, "\
3179  %6.2g radius of pre-merge centrum\n", qh premerge_centrum);
3180   if (qh postmerge_cos < REALmax/2) fprintf (fp, "\
3181  %6.2g max. cosine for post-merge angle\n", qh postmerge_cos);
3182   if (qh POSTmerge) fprintf (fp, "\
3183  %6.2g radius of post-merge centrum\n", qh postmerge_centrum);
3184   fprintf (fp, "\
3185  %6.2g max. distance for merging two simplicial facets\n\
3186  %6.2g max. roundoff error for arithmetic operations\n\
3187  %6.2g min. denominator for divisions\n\
3188   zero diagonal for Gauss: ", qh ONEmerge, REALepsilon, qh MINdenom);
3189   for (k=0; k<qh hull_dim; k++)
3190     fprintf (fp, "%6.2e ", qh NEARzero[k]);
3191   fprintf (fp, "\n\n");
3192   for (i=0 ; i<qhstat next; )
3193     qh_printstats (fp, i, &i);
3194 } /* printstatistics */
3195 #endif /* qh_KEEPstatistics */
3196 
3197 /*-------------------------------------------
3198 -printstatlevel- print level information for a statistic
3199   start is 1st level to print
3200   nop if id >= ZEND, printed, or same as initial value
3201 */
qh_printstatlevel(FILE * fp,int id,int start)3202 void qh_printstatlevel (FILE *fp, int id, int start) {
3203 #define NULLfield "       "
3204 
3205   if (id >= ZEND || qhstat printed[id])
3206     return;
3207   if (qhstat type[id] == zdoc) {
3208     fprintf (fp, "%s\n", qhstat doc[id]);
3209     return;
3210   }
3211   if (qh_nostatistic(id) || !qhstat doc[id])
3212     return;
3213   qhstat printed[id]= True;
3214   if (qhstat count[id] != -1
3215       && qhstat stats[(unsigned char)(qhstat count[id])].i == 0)
3216     fprintf (fp, " *0 cnt*");
3217   else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] == -1)
3218     fprintf (fp, " %6.2g", qhstat stats[id].r);
3219   else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] != -1)
3220     fprintf (fp, " %6.2g", qhstat stats[id].r/ qhstat stats[(unsigned char)(qhstat count[id])].i);
3221   else if (qhstat type[id] < ZTYPEreal && qhstat count[id] == -1)
3222     fprintf (fp, " %6d", qhstat stats[id].i);
3223   else if (qhstat type[id] < ZTYPEreal && qhstat count[id] != -1)
3224     fprintf (fp, " %6.2g", (realT) qhstat stats[id].i / qhstat stats[(unsigned char)(qhstat count[id])].i);
3225   fprintf (fp, " %s\n", qhstat doc[id]);
3226 } /* printstatlevel */
3227 
3228 
3229 /*-------------------------------------------------------
3230 -printstats- print statistics for a zdoc group
3231 returns:
3232   next zdoc if non-null
3233 */
qh_printstats(FILE * fp,int index,int * nextindex)3234 void qh_printstats (FILE *fp, int index, int *nextindex) {
3235   int j, nexti;
3236 
3237   if (qh_newstats (index, &nexti)) {
3238     for (j=index; j<nexti; j++)
3239       qh_printstatlevel (fp, qhstat id[j], 0);
3240     fprintf (fp, "\n");
3241   }
3242   if (nextindex)
3243     *nextindex= nexti;
3244 } /* printstats */
3245 
3246 #if qh_KEEPstatistics
3247 
3248 /*-----------------------------------------
3249 -stddev- compute the standard deviation and average from statistics
3250   tot2 is the sum of the squares
3251 notes:
3252   computes r.m.s.: (x-ave)^2 == x^2 - 2x tot/num + (tot/num)^2
3253      == tot2 - 2 tot tot/num + tot tot/num == tot2 - tot ave
3254 */
qh_stddev(int num,realT tot,realT tot2,realT * ave)3255 realT qh_stddev (int num, realT tot, realT tot2, realT *ave) {
3256   realT stddev;
3257 
3258   *ave= tot/num;
3259   stddev= sqrt (tot2/num - *ave * *ave);
3260   return stddev;
3261 } /* stddev */
3262 
3263 #endif /* qh_KEEPstatistics */
3264 
3265 #if !qh_KEEPstatistics
qh_collectstatistics(void)3266 void    qh_collectstatistics (void) {}
qh_printallstatistics(FILE * fp,const char * string)3267 void    qh_printallstatistics (FILE *fp, const char *string) {}
qh_printstatistics(FILE * fp,const char * string)3268 void    qh_printstatistics (FILE *fp, const char *string) {}
3269 #endif
3270 
3271 
3272 /*************************************************************************/
3273 /****************** implementation code from poly.c **********************/
3274 /*************************************************************************/
3275 
3276 /* Ppoly.c -- implements polygons and simplices
3277 
3278    see README, poly.h and qhull.h
3279 
3280    copyright (c) 1993-1994, The Geometry Center
3281 */
3282 
3283 /*======== functions in alphabetical order ==========*/
3284 
3285 /*-------------------------------------------------
3286 -appendfacet- appends facet to end of qh facet_list,
3287   updates qh facet_list, facet_tail, newfacet_list, facet_next
3288   increments qh numfacets
3289   assumes qh facet_list/facet_tail is defined (createsimplex)
3290 */
qh_appendfacet(facetT * facet)3291 void qh_appendfacet(facetT *facet) {
3292   facetT *tail= qh facet_tail;
3293 
3294   if (tail == qh newfacet_list)
3295     qh newfacet_list= facet;
3296   if (tail == qh facet_next)
3297     qh facet_next= facet;
3298   facet->previous= tail->previous;
3299   facet->next= tail;
3300   if (tail->previous)
3301     tail->previous->next= facet;
3302   else
3303     qh facet_list= facet;
3304   tail->previous= facet;
3305   qh num_facets++;
3306   trace4((qh ferr, "qh_appendfacet: append f%d to facet_list\n", facet->id));
3307 } /* appendfacet */
3308 
3309 
3310 /*-------------------------------------------------
3311 -appendvertex- appends vertex to end of qh vertex_list,
3312   updates qh vertex_list, vertex_tail, newvertex_list
3313   increments qh num_vertices
3314   assumes qh vertex_list/vertex_tail is defined (createsimplex)
3315 */
qh_appendvertex(vertexT * vertex)3316 void qh_appendvertex (vertexT *vertex) {
3317   vertexT *tail= qh vertex_tail;
3318 
3319   if (tail == qh newvertex_list)
3320     qh newvertex_list= vertex;
3321   vertex->previous= tail->previous;
3322   vertex->next= tail;
3323   if (tail->previous)
3324     tail->previous->next= vertex;
3325   else
3326     qh vertex_list= vertex;
3327   tail->previous= vertex;
3328   qh num_vertices++;
3329   trace4((qh ferr, "qh_appendvertex: append v%d to vertex_list\n", vertex->id));
3330 } /* appendvertex */
3331 
3332 
3333 /*-------------------------------------------------
3334 -attachnewfacets- attach horizon facets to new facets in qh newfacet_list
3335   if (qh ONLYgood)
3336     newfacets have neighbor and ridge links to horizon but not vice versa
3337   else
3338     newfacets attached to horizon and visible facets attached to new
3339   qh visible_list is all visible facets
3340 returns:
3341   horizon facets linked to new facets
3342      ridges changed from visible facets to new facets
3343      simplicial ridges deleted
3344      for non-simplicial horizon facets, the first neighbor is a new facet
3345   qh visible_list, no ridges valid, only newfacet neighbors (if any)
3346      sets qh NEWfacets
3347   if qh VERTEXneighbors, update neighbors for each vertex
3348   interior vertices added to qh del_vertices for later partitioning
3349 */
qh_attachnewfacets(void)3350 void qh_attachnewfacets (void ) {
3351   facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible;
3352   ridgeT *ridge, **ridgep;
3353   vertexT *vertex, **vertexp;
3354 
3355   qh NEWfacets= True;
3356   if (qh ONLYgood) {
3357     trace3((qh ferr, "qh_attachnewfacets: delete interior ridges\n"));
3358     qh visit_id++;
3359     FORALLvisible_facets {
3360       visible->visitid= qh visit_id;
3361       if (visible->ridges) {
3362         FOREACHridge_(visible->ridges) {
3363           neighbor= otherfacet_(ridge, visible);
3364           if ((int)neighbor->visitid == qh visit_id
3365           || (!neighbor->visible && neighbor->simplicial)) {
3366             if (!neighbor->visible)  /* delete ridge for simplicial horizon */
3367 	      qh_setdel (neighbor->ridges, ridge);
3368 	    qh_setfree (&(ridge->vertices)); /* delete on 2nd visit */
3369 	    qh_memfree (ridge, sizeof(ridgeT));
3370 	  }
3371         }
3372         SETfirst_(visible->ridges)= NULL;
3373       }
3374       SETfirst_(visible->neighbors)= NULL;
3375       SETsecond_(visible->neighbors)= NULL;
3376     }
3377     trace1((qh ferr, "qh_attachnewfacets: attach horizon facets to new facets\n"));
3378     FORALLnew_facets {
3379       horizon= (facetT *)SETfirst_(newfacet->neighbors);
3380       if (horizon->simplicial) {
3381         visible= NULL;
3382         FOREACHneighbor_(horizon) {   /* may have more than one horizon ridge */
3383 	  if (neighbor->visible) {
3384 	    if (visible) {
3385 	      if (qh_setequal_skip (newfacet->vertices, 0, horizon->vertices,
3386 		     SETindex_(horizon->neighbors, neighbor))) {
3387 	        visible= neighbor;
3388 	        break;
3389 	      }
3390 	    }else
3391 	      visible= neighbor;
3392 	  }
3393         }
3394         if (visible) {
3395           SETfirst_(visible->neighbors)= newfacet;
3396 	  qh_setreplace (horizon->neighbors, visible, newfacet);
3397         }
3398 
3399 	else qhull_fatal(34);
3400 
3401       }else { /* non-simplicial, with a ridge for newfacet */
3402         FOREACHneighbor_(horizon) {    /* may hold for many new facets */
3403 	  if (neighbor->visible) {
3404 	    SETfirst_(neighbor->neighbors)= newfacet;
3405 	    qh_setdelnth (horizon->neighbors,
3406 			SETindex_(horizon->neighbors, neighbor));
3407 	    neighborp--; /* repeat */
3408 	  }
3409         }
3410         qh_setappend (&horizon->neighbors, newfacet);
3411         ridge= (ridgeT *)SETfirst_(newfacet->ridges);
3412         if (ridge->top == horizon)
3413           ridge->bottom= newfacet;
3414         else
3415           ridge->top= newfacet;
3416       }
3417     } /* newfacets */
3418     if (qh PRINTstatistics) {
3419       FORALLvisible_facets {
3420         if (!SETfirst_(visible->neighbors))
3421           zinc_(Zinsidevisible);
3422       }
3423     }
3424   }
3425   trace3((qh ferr, "qh_attachnewfacets: delete interior vertices and update vertex->neighbors\n"));
3426   if (qh VERTEXneighbors) {
3427     FORALLvisible_facets {
3428       FOREACHvertex_(visible->vertices) {
3429         if (vertex->newlist)
3430           qh_setdel (vertex->neighbors, visible);
3431         else if (!vertex->deleted) {
3432   	  FOREACHneighbor_(vertex) { /* this can happen under merging,
3433 				      see checkfacet() */
3434 	    if (!neighbor->visible)
3435 	      break;
3436 	  }
3437 	  if (neighbor)
3438 	    qh_setdel (vertex->neighbors, visible);
3439 	  else {
3440 	    vertex->deleted= True;
3441 	    qh_setappend (&qh del_vertices, vertex);
3442 	    trace2((qh ferr, "qh_attachnewfacets: delete vertex p%d (v%d) in f%d\n",
3443 		  qh_pointid(vertex->point), vertex->id, visible->id));
3444   	  }
3445         }
3446       }
3447     }
3448     FORALLnew_facets {
3449       FOREACHvertex_(newfacet->vertices)
3450         qh_setappend (&vertex->neighbors, newfacet);
3451     }
3452   }else {  /* !VERTEXneighbors */
3453     FORALLvisible_facets {
3454       FOREACHvertex_(visible->vertices) {
3455         if (!vertex->newlist && !vertex->deleted) {
3456           vertex->deleted= True;
3457 	  qh_setappend (&qh del_vertices, vertex);
3458 	  trace2((qh ferr, "qh_attachnewfacets: delete vertex p%d (v%d) in f%d\n",
3459 		  qh_pointid(vertex->point), vertex->id, visible->id));
3460   	}
3461       }
3462     }
3463   }
3464 } /* attachnewfacets */
3465 
3466 /*-----------------------------------------------
3467 -check_bestdist- check that points are within max_outside of the nearest facet
3468   if ONLYgood, ignores !good facets
3469   see: check_maxout
3470 */
qh_check_bestdist(void)3471 void qh_check_bestdist (void) {
3472   boolT waserror= False, isoutside;
3473   facetT *facet, *bestfacet, *errfacet1= NULL, *errfacet2= NULL;
3474   realT dist, maxoutside;
3475   pointT *point;
3476   int numpart, facet_i, facet_n, notgood= 0;
3477   setT *facets;
3478 
3479   maxoutside= fmax_(qh max_outside, qh DISTround);
3480   maxoutside += 2 * qh DISTround;
3481   /* 1 DISTround to actual point and another DISTround to computed point */
3482   trace1((qh ferr, "qh_check_bestdist: check that all points are within %2.2g of best facet\n", maxoutside));
3483   facets= qh_pointfacet (/*qh facet_list*/);
3484   if (!qh_QUICKhelp && qh PRINTprecision)
3485     fprintf (qh ferr, "\n\
3486 qhull output completed.  Verifying that %d points are\n\
3487 below %2.2g of the nearest %sfacet.\n",
3488 	     qh_setsize(facets), maxoutside, (qh ONLYgood ?  "good " : ""));
3489   FOREACHfacet_i_(facets) {
3490     zinc_(Ztotverify);
3491     if (!facet)
3492       facet= qh facet_list;
3493     point= qh_point(facet_i);
3494     if (point == qh GOODpointp)
3495       continue;
3496     bestfacet= qh_findbest (point, facet, qh_ALL, 0,
3497 			    &dist, &isoutside, &numpart);
3498     zadd_(Zverifypart, numpart);
3499     if (dist > maxoutside) {
3500       if (qh ONLYgood && !bestfacet->good
3501 	  && !((bestfacet= qh_findgooddist (point, bestfacet, &dist))
3502 	       && dist > maxoutside))
3503 	notgood++;
3504       else {
3505 	waserror= True;
3506 	fprintf(qh ferr, "qhull precision error: point p%d is outside facet f%d, distance = %6.8g maxoutside= %6.8g\n",
3507 		facet_i, bestfacet->id, dist, maxoutside);
3508 	errfacet2= errfacet1;
3509 	errfacet1= bestfacet;
3510       }
3511     }
3512   }
3513   qh_settempfree (&facets);
3514 
3515   if (waserror) qhull_fatal(35);
3516 
3517 } /* check_bestdist */
3518 
3519 /*-----------------------------------------------
3520 -check_maxout- updates max_outside by checking all points against bestfacet
3521   updates facet->maxoutside via findbest
3522   updates facet->coplanarset to qh min_vertex
3523   if PRINTnone, updates min_vertex for printsummary()
3524   if ONLYgood, ignores !good facets
3525   see check_bestdist
3526 notes:
3527   may not need to check inside points if KEEPcoplanar
3528      (since coplanar is now min_vertex instead of -DISTround)
3529 */
qh_check_maxout(void)3530 void qh_check_maxout (void) {
3531   boolT isoutside;
3532   facetT *facet, *bestfacet, *neighbor, **neighborp;
3533   realT dist, maxoutside, minvertex;
3534   pointT *point;
3535   int numpart, facet_i, facet_n, notgood= 0;
3536   setT *facets, *vertices= NULL;
3537   vertexT *vertex;
3538 
3539   maxoutside= minvertex= 0;
3540   trace1((qh ferr, "qh_check_maxout: determine actual maxoutside and minoutside\n"));
3541   facets= qh_pointfacet (/*qh facet_list*/);
3542   if (qh PRINTout[0] == qh_PRINTnone || qh PRINTsummary) {
3543     vertices= qh_pointvertex (/*qh facet_list*/);
3544     FORALLvertices {
3545       FOREACHneighbor_(vertex) {
3546 	zinc_(Zverifypart);
3547 	qh_distplane (vertex->point, neighbor, &dist);
3548 	minimize_(minvertex, dist);
3549 	if (-dist > qh TRACEdist
3550 	    || neighbor == qh tracefacet || vertex == qh tracevertex)
3551 	  fprintf (qh ferr, "qh_check_maxout: p%d (v%d) is %.2g below f%d\n",
3552 		   qh_pointid (vertex->point), vertex->id, dist, neighbor->id);
3553       }
3554     }
3555     if (qh MERGING)
3556       wmin_(Wminvertex, qh min_vertex);
3557     qh min_vertex= minvertex;
3558   }
3559   FOREACHfacet_i_(facets) {
3560     if (True) { /* inside points can end up outside after merging */
3561       zinc_(Ztotverify);
3562       if (!facet)
3563         facet= qh facet_list;
3564       point= qh_point(facet_i);
3565       if (point == qh GOODpointp)
3566 	continue;
3567       bestfacet= qh_findbest (point, facet, qh_ALL, 0,
3568 			    &dist, &isoutside, &numpart);
3569       zadd_(Zverifypart, numpart);
3570       if (dist > maxoutside) {
3571         if (qh ONLYgood && !bestfacet->good
3572         && !((bestfacet= qh_findgooddist (point, bestfacet, &dist))
3573              && dist > maxoutside))
3574           notgood++;
3575         else
3576 	  maxoutside= dist;
3577       }
3578       if (!facet && dist > qh min_vertex)
3579 	qh_partitioncoplanar (point, bestfacet, &dist);
3580       if (dist > qh TRACEdist || bestfacet == qh tracefacet)
3581 	  fprintf (qh ferr, "qh_check_maxout: p%d is %.2g above f%d\n",
3582 		   qh_pointid (point), dist, bestfacet->id);
3583     }
3584   }
3585   qh_settempfree (&vertices);
3586   qh_settempfree (&facets);
3587   wmax_(Wmaxoutside, qh max_outside);
3588   qh max_outside= maxoutside;
3589   trace1((qh ferr, "qh_check_maxout: maxoutside %2.2g outside of not good %d\n",
3590        maxoutside, notgood));
3591 } /* check_maxout */
3592 
3593 /*----------------------------------------
3594 -check_output- performs the checks at the end of qhull algorithm
3595   does not check points (may take a long time)
3596 */
qh_check_output(void)3597 void qh_check_output (void) {
3598   int i;
3599 
3600   if (qh STOPcone)
3601     return;
3602   if (qh VERIFYoutput | qh IStracing | qh CHECKfrequently) {
3603     qh_checkpolygon (qh facet_list);
3604     qh_checkflipped_all (qh facet_list);
3605     qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
3606   }else if (!qh MERGING && qh_newstats (qhstat precision, &i)) {
3607     qh_checkflipped_all (qh facet_list);
3608     qh_checkconvex (qh facet_list, qh_ALGORITHMfault);
3609   }
3610 } /* check_output */
3611 
3612 
3613 
3614 /*-------------------------------------------------------------
3615 -check_point- check that point is not outside facet
3616   if maxerror, doesn't report an error
3617 */
qh_check_point(pointT * point,facetT * facet,realT * maxoutside,facetT ** errfacet1,facetT ** errfacet2)3618 void qh_check_point (pointT *point, facetT *facet, realT *maxoutside, facetT **errfacet1, facetT **errfacet2) {
3619   realT dist;
3620 
3621   zinc_(Zverifypart);
3622   qh_distplane(point, facet, &dist);
3623   if (dist > *maxoutside) {
3624     *errfacet2= *errfacet1;
3625     *errfacet1= facet;
3626     fprintf(qh ferr, "qhull precision error: point p%d is outside facet f%d, distance = %6.8g maxoutside= %6.8g\n",
3627 	      qh_pointid(point), facet->id, dist, *maxoutside);
3628   }
3629 } /* qh_check_point */
3630 
3631 
3632 /*-------------------------------------------------
3633 -check_points- checks that all points are inside all facets
3634      uses findbest if lots of points
3635      ignores flipped facets
3636 */
qh_check_points(void)3637 void qh_check_points (void) {
3638   facetT *facet, *errfacet1= NULL, *errfacet2= NULL;
3639   realT total, maxoutside;
3640   pointT *point, **pointp, *pointtemp;
3641 
3642   maxoutside= fmax_(qh max_outside, qh DISTround);
3643   maxoutside += 2* qh DISTround;
3644   /* 1 DISTround to actual point and another DISTround to computed point */
3645   if (qh RANDOMdist) /* repeated computations can differ by 2*distround */
3646     maxoutside += qh DISTround;
3647   trace1((qh ferr, "qh_check_points: check all points below %2.2g of all facet planes\n",
3648 	  maxoutside));
3649   if (qh num_good)
3650      total= (float) qh num_good * qh num_points;
3651   else
3652      total= (float) qh num_facets * qh num_points;
3653   if (total >= qh_VERIFYdirect && !qh MERGING)  /* MERGING qh_check_maxout */
3654     qh_check_bestdist();
3655   else {
3656     if (!qh_QUICKhelp  && qh PRINTprecision) { /* miss counts other_points and !good facets */
3657       if (qh PREmerge && !qh KEEPcoplanar && zzval_(Zcoplanarpart) > 10)
3658 	fprintf (qh ferr, "\n\
3659 qhull input warning: pre-merging ('C-n' or 'A-n') without retaining coplanar\n\
3660 points ('Qc').  Verify may report that an outer plane is incorrect.\n");
3661       fprintf (qh ferr, "\n\
3662 Output completed.  Verifying that all points are below %2.2g of\n\
3663 all %sfacets.  Will make %2.0f distance computations.\n",
3664 	       maxoutside, (qh ONLYgood ?  "good " : ""), total);
3665     }
3666     FORALLfacets {
3667       if (!facet->good && qh ONLYgood)
3668         continue;
3669       if (facet->flipped)
3670         continue;
3671 #if qh_MAXoutside
3672       maxoutside= facet->maxoutside + 2* qh DISTround;
3673       /* 1 DISTround to actual point and another DISTround to computed point */
3674 #endif
3675       FORALLpoints {
3676 	if (point != qh GOODpointp)
3677 	  qh_check_point (point, facet, &maxoutside, &errfacet1, &errfacet2);
3678       }
3679       FOREACHpoint_(qh other_points) {
3680 	if (point != qh GOODpointp)
3681 	  qh_check_point (point, facet, &maxoutside, &errfacet1, &errfacet2);
3682       }
3683     }
3684 
3685     if (errfacet1) qhull_fatal(36);
3686 
3687   }
3688 } /* check_points */
3689 
3690 
3691 /*-------------------------------------------------
3692 -checkconvex- check that each ridge in facetlist is convex
3693 returns:
3694     counts Zconcaveridges and Zcoplanarridges
3695     errors if concaveridge or if merging an coplanar ridge
3696 note:
3697     optimized for simplicial facets
3698 */
qh_checkconvex(facetT * facetlist,int fault)3699 void qh_checkconvex(facetT *facetlist, int fault) {
3700   facetT *facet, *neighbor, **neighborp, *errfacet1=NULL, *errfacet2=NULL;
3701   vertexT *vertex;
3702   realT dist;
3703   pointT *centrum;
3704   boolT waserror= False;
3705   int neighbor_i;
3706 
3707   trace1((qh ferr, "qh_checkconvex: check all ridges are convex\n"));
3708   zzval_(Zconcaveridges)= 0;
3709   zzval_(Zcoplanarridges)= 0;
3710   FORALLfacet_(facetlist) {
3711     if (facet->flipped) {
3712       fprintf (qh ferr, "qhull precision error: f%d is flipped (interior point is outside)\n",
3713 	       facet->id);
3714       errfacet1= facet;
3715       waserror= True;
3716       continue;
3717     }
3718     if (!qh MERGING) {  /* simplicial facet */
3719       neighbor_i= 0;
3720       FOREACHneighbor_(facet) {
3721         vertex= (vertexT *)SETelem_(facet->vertices, neighbor_i++);
3722         zzinc_(Zdistconvex);
3723         qh_distplane (vertex->point, neighbor, &dist);
3724         if (dist > -qh DISTround) {
3725 
3726 	  if (fault == qh_DATAfault) qhull_fatal(37);
3727 
3728           if (dist > qh DISTround) {
3729             zzinc_(Zconcaveridges);
3730             fprintf (qh ferr, "qhull precision error: f%d is concave to f%d, since p%d (v%d) is %6.4g above\n",
3731               facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
3732             errfacet1= facet;
3733             errfacet2= neighbor;
3734             waserror= True;
3735           }else {
3736             zzinc_(Zcoplanarridges);
3737             trace0((qh ferr, "qhull precision error: f%d may be coplanar to f%d, since p%d (v%d) is within %6.4g\n",
3738               facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist));
3739           }
3740         }
3741       }
3742     }else { /* qh MERGING */
3743       if (qh CENTERtype == qh_centrum) {
3744         if (!facet->center)
3745           facet->center= qh_getcentrum (facet);
3746         centrum= facet->center;
3747       }else
3748         centrum= qh_getcentrum(facet);
3749       FOREACHneighbor_(facet) {
3750         zzinc_(Zdistconvex);
3751         qh_distplane (centrum, neighbor, &dist);
3752         if (dist > qh DISTround) {
3753           zzinc_(Zconcaveridges);
3754           fprintf (qh ferr, "qhull precision error: f%d is concave to f%d, since its centrum is %6.4g above\n",
3755             facet->id, neighbor->id, dist);
3756           errfacet1= facet;
3757           errfacet2= neighbor;
3758           waserror= True;
3759         }else if (dist >= 0.0) {   /* if arithmetic always rounds the same,
3760 				     can test against centrum radius instead */
3761           zzinc_(Zcoplanarridges);
3762           fprintf (qh ferr, "qhull precision error: f%d is coplanar or concave to f%d, since its centrum is %6.4g above\n",
3763             facet->id, neighbor->id, dist);
3764 	  errfacet1= facet;
3765 	  errfacet2= neighbor;
3766 	  waserror= True;
3767         }
3768       }
3769       if (qh CENTERtype != qh_centrum)
3770         qh_memfree(centrum, qh normal_size);
3771     }
3772   }
3773 
3774   if (waserror && !qh FORCEoutput) qhull_fatal(38);
3775 
3776 } /* checkconvex */
3777 
3778 
3779 /*-------------------------------------------------
3780 -checkfacet- checks for consistency errors in facet
3781     vertex ids are inverse sorted
3782     unless newmerge, at least hull_dim neighbors and vertices (exactly if simplicial)
3783     if non-simplicial, at least as many ridges as neighbors
3784     neighbors are not duplicated
3785     ridges are not duplicated
3786     in 3-d, ridges=verticies
3787     (hull_dim-1) ridge vertices
3788     neighbors are reciprocated
3789     ridge neighbors are facet neighbors and a ridge for every neighbor
3790     simplicial neighbors match facetintersect
3791     vertex intersection matches vertices of common ridges
3792     vertex neighbors and facet vertices agree
3793   sets waserror if any error occurs
3794   uses neighbor->seen
3795 */
qh_checkfacet(facetT * facet,boolT newmerge,boolT * waserrorp)3796 void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp) {
3797   facetT *neighbor, **neighborp, *errother=NULL;
3798   ridgeT *ridge, **ridgep, *errridge= NULL;
3799   vertexT *vertex, **vertexp;
3800   unsigned previousid= INT_MAX;
3801   int numneighbors, numvertices, numridges=0, numRvertices=0;
3802   boolT waserror= False;
3803   int skipA, skipB;
3804   setT *intersection;
3805 
3806   if (facet->visible) qhull_fatal(39);
3807 
3808   if (!facet->normal) {
3809     fprintf (qh ferr, "qhull internal error (checkfacet): facet f%d does not have  a normal\n",
3810       facet->id);
3811     waserror= True;
3812   }
3813   qh_setcheck (facet->vertices, "vertices for f", facet->id);
3814   qh_setcheck (facet->ridges, "ridges for f", facet->id);
3815   qh_setcheck (facet->outsideset, "outsideset for f", facet->id);
3816   qh_setcheck (facet->coplanarset, "coplanarset for f", facet->id);
3817   qh_setcheck (facet->neighbors, "neighbors for f", facet->id);
3818   FOREACHvertex_(facet->vertices) {
3819     if (vertex->deleted) {
3820       fprintf(qh ferr, "qhull internal error (checkfacet): deleted vertex v%d in f%d\n", vertex->id, facet->id);
3821 
3822       /*
3823       qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
3824       NO LONGER IN SERVICE */
3825 
3826       waserror= True;
3827     }
3828     if (vertex->id >= previousid) {
3829       fprintf(qh ferr, "qhull internal error (checkfacet): vertices of f%d are not in descending id order at v%d\n", facet->id, vertex->id);
3830       waserror= True;
3831       break;
3832     }
3833     previousid= vertex->id;
3834   }
3835   numneighbors= qh_setsize(facet->neighbors);
3836   numvertices= qh_setsize(facet->vertices);
3837   numridges= qh_setsize(facet->ridges);
3838   if (facet->simplicial) {
3839     if (numvertices+numneighbors != 2*qh hull_dim && !qh_facetdegen(facet)) {
3840       fprintf(qh ferr, "qhull internal error (checkfacet): for simplicial facet f%d, #vertices %d + #neighbors %d != 2*qh hull_dim\n",
3841                 facet->id, numvertices, numneighbors);
3842       qh_setprint (qh ferr, "", facet->neighbors);
3843       waserror= True;
3844     }
3845   }else { /* non-simplicial */
3846     if (!newmerge
3847      &&(numvertices < qh hull_dim || numneighbors < qh hull_dim)
3848      && !qh_facetdegen(facet)) {
3849       fprintf(qh ferr, "qhull internal error (checkfacet): for facet f%d, #vertices %d or #neighbors %d < qh hull_dim\n",
3850          facet->id, numvertices, numneighbors);
3851        waserror= True;
3852     }
3853     if (numridges < numneighbors
3854     ||(qh hull_dim == 3 && !qh NEWmerges && numvertices != numridges)
3855     ||(qh hull_dim == 2 && numridges + numvertices + numneighbors != 6)) {
3856       if (!qh_facetdegen(facet)) {
3857 	fprintf(qh ferr, "qhull internal error (checkfacet): for facet f%d, #ridges %d < #neighbors %d or (3-d) != #vertices %d or (2-d) not all 2\n",
3858 	    facet->id, numridges, numneighbors, numvertices);
3859 	waserror= True;
3860       }
3861     }
3862   }
3863   FOREACHneighbor_(facet) {
3864 
3865     if (neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge)
3866       qhull_fatal(40);
3867 
3868     neighbor->seen= True;
3869   }
3870   FOREACHneighbor_(facet) {
3871     if (!qh_setin(neighbor->neighbors, facet)) {
3872       fprintf(qh ferr, "qhull internal error (checkfacet): facet f%d has neighbor f%d, but f%d does not have neighbor f%d\n",
3873 	      facet->id, neighbor->id, neighbor->id, facet->id);
3874       errother= neighbor;
3875       waserror= True;
3876     }
3877     if (!neighbor->seen) {
3878       fprintf(qh ferr, "qhull internal error (checkfacet): facet f%d has a duplicate neighbor f%d\n",
3879 	      facet->id, neighbor->id);
3880       errother= neighbor;
3881       waserror= True;
3882     }
3883     neighbor->seen= False;
3884   }
3885   FOREACHridge_(facet->ridges) {
3886     qh_setcheck (ridge->vertices, "vertices for r", ridge->id);
3887     ridge->seen= False;
3888     if (ridge->mergeridge && !newmerge) {
3889       fprintf (qh ferr, "qhull internal error (checkfacet): mergeridge r%d still in facetlist\n", ridge->id);
3890 
3891       /*
3892       qh_errprint ("ERRONEOUS", NULL, NULL, ridge, NULL);
3893       NO LONGER IN SERVICE */
3894 
3895       waserror= True;
3896     }
3897   }
3898   FOREACHridge_(facet->ridges) {
3899     if (ridge->seen) {
3900       fprintf(qh ferr, "qhull internal error (checkfacet): facet f%d has a duplicate ridge r%d\n",
3901 	      facet->id, ridge->id);
3902       errridge= ridge;
3903       waserror= True;
3904     }
3905     ridge->seen= True;
3906     numRvertices= qh_setsize(ridge->vertices);
3907     if (numRvertices != qh hull_dim - 1) {
3908       fprintf(qh ferr, "qhull internal error (checkfacet): ridge between f%d and f%d has %d vertices\n",
3909                 ridge->top->id, ridge->bottom->id, numRvertices);
3910       errridge= ridge;
3911       waserror= True;
3912     }
3913     neighbor= otherfacet_(ridge, facet);
3914     neighbor->seen= True;
3915     if (!qh_setin(facet->neighbors, neighbor)) {
3916       fprintf(qh ferr, "qhull internal error (checkfacet): for facet f%d, neighbor f%d of ridge r%d not in facet\n",
3917            facet->id, neighbor->id, ridge->id);
3918       errridge= ridge;
3919       waserror= True;
3920     }
3921   }
3922   if (!facet->simplicial) {
3923     FOREACHneighbor_(facet) {
3924       if (!neighbor->seen) {
3925         fprintf(qh ferr, "qhull internal error (checkfacet): facet f%d does not have a ridge for neighbor f%d\n",
3926 	      facet->id, neighbor->id);
3927 	errother= neighbor;
3928         waserror= True;
3929       }
3930       intersection= qh_vertexintersect_new(facet->vertices, neighbor->vertices);
3931       qh_settemppush (intersection);
3932       FOREACHvertex_(facet->vertices) {
3933 	vertex->seen= False;
3934 	vertex->seen2= False;
3935       }
3936       FOREACHvertex_(intersection)
3937 	vertex->seen= True;
3938       FOREACHridge_(facet->ridges) {
3939 	if (neighbor != otherfacet_(ridge, facet))
3940 	    continue;
3941 	FOREACHvertex_(ridge->vertices) {
3942 
3943 	  if (!vertex->seen) qhull_fatal(41);
3944 
3945 	  vertex->seen2= True;
3946 	}
3947       }
3948       if (!newmerge) {
3949 	FOREACHvertex_(intersection) {
3950 	  if (!vertex->seen2) {
3951 	    if (qh IStracing >=3 || !qh MERGING) {
3952 	      fprintf (qh ferr, "qhull precision error (checkfacet): vertex v%d in f%d intersect f%d but\n\
3953  not in a ridge.  This is ok under merging.  Last point was p%d\n",
3954 		     vertex->id, facet->id, neighbor->id, qh furthest_id);
3955 
3956 	      if (!qh FORCEoutput && !qh MERGING) qhull_fatal(42);
3957 
3958 	    }
3959 	  }
3960 	}
3961       }
3962       qh_settempfree (&intersection);
3963     }
3964   }else { /* simplicial */
3965     FOREACHneighbor_(facet) {
3966       if (neighbor->simplicial) {
3967 	skipA= SETindex_(facet->neighbors, neighbor);
3968 	skipB= qh_setindex (neighbor->neighbors, facet);
3969 	if (!qh_setequal_skip (facet->vertices, skipA, neighbor->vertices, skipB)) {
3970 	  fprintf (qh ferr, "qhull internal error (checkfacet): facet f%d skip %d and neighbor f%d skip %d do not match \n",
3971 		   facet->id, skipA, neighbor->id, skipB);
3972 	  errother= neighbor;
3973 	  waserror= True;
3974 	}
3975       }
3976     }
3977   }
3978 
3979   if (waserror) {
3980 
3981     /*
3982     qh_errprint("ERRONEOUS", facet, errother, errridge, NULL);
3983     NO LONGER IN SERVICE */
3984 
3985     *waserrorp= True;
3986   }
3987 } /* checkfacet */
3988 
3989 
3990 /*-------------------------------------------------
3991 -checkflipped- checks facet orientation to interior point
3992   tests against 0 if !allerror since tested against DISTround before
3993 returns:
3994   False if flipped orientation (sets facet->flipped)
3995   distance if non-NULL
3996 */
qh_checkflipped(facetT * facet,realT * distp,boolT allerror)3997 boolT qh_checkflipped (facetT *facet, realT *distp, boolT allerror) {
3998   realT dist;
3999 
4000   if (facet->flipped && !distp)
4001     return False;
4002   zzinc_(Zdistcheck);
4003   qh_distplane(qh interior_point, facet, &dist);
4004   if (distp)
4005     *distp= dist;
4006   if ((allerror && dist > -qh DISTround)|| (!allerror && dist >= 0.0)) {
4007     facet->flipped= True;
4008     zzinc_(Zflippedfacets);
4009     trace0((qh ferr, "qh_checkflipped: facet f%d is flipped, distance= %6.12g\n",
4010               facet->id, dist));
4011     return False;
4012   }
4013   return True;
4014 } /* checkflipped */
4015 
4016 /*-------------------------------------------------
4017 -checkflipped_all- checks orientation of facets in list against interior point
4018 */
qh_checkflipped_all(facetT * facetlist)4019 void qh_checkflipped_all (facetT *facetlist) {
4020   facetT *facet;
4021   boolT waserror= False;
4022   realT dist;
4023 
4024   if (facetlist == qh facet_list)
4025     zzval_(Zflippedfacets)= 0;
4026   FORALLfacet_(facetlist) {
4027     if (!qh_checkflipped (facet, &dist, (boolT)!qh_ALL)) {
4028       fprintf(qh ferr, "qhull precision error: facet f%d is flipped, distance= %6.12g\n",
4029 	      facet->id, dist);
4030       if (!qh FORCEoutput) {
4031 
4032 	/*
4033 	qh_errprint("ERRONEOUS", facet, NULL, NULL, NULL);
4034 	NO LONGER IN SERVICE */
4035 
4036 	waserror= True;
4037       }
4038     }
4039   }
4040   if (waserror) qhull_fatal(43);
4041 
4042 } /* checkflipped_all */
4043 
4044 /*-------------------------------------------------
4045 -checkpolygon- checks the correctness of the structure
4046   check num_facets and num_vertices if qh facet_list
4047   call with either qh facet_list or qh newfacet_list
4048 */
qh_checkpolygon(facetT * facetlist)4049 void qh_checkpolygon(facetT *facetlist) {
4050   facetT *facet;
4051   vertexT *vertex, **vertexp, *vertexlist;
4052   int numfacets= 0, numvertices= 0, numridges= 0;
4053   boolT waserror= False, nextseen= False, visibleseen= False;
4054 
4055   trace1((qh ferr, "qh_checkpolygon: check all facets from f%d\n", facetlist->id));
4056   if (facetlist != qh facet_list || qh ONLYgood)
4057     nextseen= True;
4058   FORALLfacet_(facetlist) {
4059     if (facet == qh visible_list)
4060       visibleseen= True;
4061     if (!facet->visible) {
4062       if (!nextseen) {
4063 	if (facet == qh facet_next)
4064 	  nextseen= True;
4065 	else
4066 
4067 	  if (qh_setsize (facet->outsideset)) qhull_fatal(44);
4068 
4069       }
4070       numfacets++;
4071       qh_checkfacet(facet, False, &waserror);
4072     }
4073   }
4074 
4075   if (qh visible_list && !visibleseen && facetlist == qh facet_list)
4076     qhull_fatal(45);
4077 
4078   if (facetlist == qh facet_list)
4079     vertexlist= qh vertex_list;
4080   else if (facetlist == qh newfacet_list)
4081     vertexlist= qh newvertex_list;
4082   else
4083     vertexlist= NULL;
4084   FORALLvertex_(vertexlist) {
4085     vertex->seen= False;
4086     vertex->visitid= 0;
4087   }
4088   FORALLfacet_(facetlist) {
4089     if (facet->visible)
4090       continue;
4091     if (facet->simplicial)
4092       numridges += qh hull_dim;
4093     else
4094       numridges += qh_setsize (facet->ridges);
4095     FOREACHvertex_(facet->vertices) {
4096       vertex->visitid++;
4097       if (!vertex->seen) {
4098 	vertex->seen= True;
4099 	numvertices++;
4100 	if (qh_pointid (vertex->point) == -1) {
4101 	  fprintf (qh ferr, "qhull internal error (checkpolygon): unknown point %p for vertex v%d first_point %p\n",
4102 		   static_cast<void *>(vertex->point), vertex->id,
4103 		   static_cast<void *>(qh first_point));
4104 	  waserror= True;
4105 	}
4106       }
4107     }
4108   }
4109   qh vertex_visit += numfacets;
4110   if (facetlist == qh facet_list) {
4111     if (numfacets != qh num_facets - qh num_visible) {
4112       fprintf(qh ferr, "qhull internal error (checkpolygon): actual number of facets is %d, cumulative facet count is %d\n",
4113 	      numfacets, qh num_facets- qh num_visible);
4114       waserror= True;
4115     }
4116     qh vertex_visit++;
4117     if (qh VERTEXneighbors) {
4118       FORALLvertices {
4119 	qh_setcheck (vertex->neighbors, "neighbors for v", vertex->id);
4120         if ((int)vertex->visitid != qh vertex_visit && !vertex->deleted) {
4121           if ((int)vertex->visitid != qh_setsize (vertex->neighbors)) {
4122             fprintf (qh ferr, "qhull internal error (checkpolygon): v%d neighbors is wrong, actually in %d facets\n",
4123               vertex->id, vertex->visitid);
4124 
4125 	    /*
4126             qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
4127 	    NO LONGER IN SERVICE */
4128 
4129 	    waserror= True;
4130           }
4131         }
4132       }
4133     }
4134     if (numvertices != qh num_vertices - qh_setsize(qh del_vertices)) {
4135       fprintf(qh ferr, "qhull internal error (checkpolygon): actual number of vertices is %d, cumulative vertex count is %d\n",
4136 	      numvertices, qh num_vertices - qh_setsize(qh del_vertices));
4137       waserror= True;
4138     }
4139     if (qh hull_dim == 2 && numvertices != numfacets) {
4140       fprintf (qh ferr, "qhull internal error (checkpolygon): #vertices %d != #facets %d\n",
4141         numvertices, numfacets);
4142       waserror= True;
4143     }
4144     if (qh hull_dim == 3 && numvertices + numfacets - numridges/2 != 2) {
4145       fprintf (qh ferr, "qhull internal error (checkpolygon): #vertices %d + #facets %d - #edges %d != 2\n",
4146         numvertices, numfacets, numridges/2);
4147       waserror= True;
4148     }
4149   }
4150 
4151   if (waserror) qhull_fatal(46);
4152 
4153 } /* checkpolygon */
4154 
4155 
4156 /*-------------------------------------------------
4157 -checkvertex- check vertex for consistency
4158 notes:
4159   neighbors checked efficiently in checkpolygon
4160 */
qh_checkvertex(vertexT * vertex)4161 void qh_checkvertex (vertexT *vertex) {
4162   boolT waserror= False;
4163   facetT *neighbor, **neighborp, *errfacet=NULL;
4164 
4165   if (qh_pointid (vertex->point) == -1) {
4166     fprintf (qh ferr, "qhull internal error (checkvertex): unknown point id %p\n",
4167 	     static_cast<void *>(vertex->point));
4168     waserror= True;
4169   }
4170   if (vertex->id >= qh vertex_id) {
4171     fprintf (qh ferr, "qhull internal error (checkvertex): unknown vertex id %d\n", vertex->id);
4172     waserror= True;
4173   }
4174   if (!waserror && !vertex->deleted) {
4175     FOREACHneighbor_(vertex) {
4176       if (!qh_setin (neighbor->vertices, vertex)) {
4177 	fprintf (qh ferr, "qhull internal error (checkvertex): neighbor f%d does not contain v%d\n", neighbor->id, vertex->id);
4178 	errfacet= neighbor;
4179 	waserror= True;
4180       }
4181     }
4182   }
4183 
4184   if (waserror) qhull_fatal(47);
4185 
4186 } /* checkvertex */
4187 
4188 /*-------------------------------------------------
4189 -clearcenters- clear old data from facet->center
4190   sets new centertype
4191   nop if CENTERtype is the same
4192 */
qh_clearcenters(int type)4193 void qh_clearcenters (int type) {
4194   facetT *facet;
4195 
4196   if (qh CENTERtype != type) {
4197     FORALLfacets {
4198       if (facet->center) {
4199         if (qh CENTERtype == qh_voronoi)
4200           qh_memfree (facet->center, qh center_size);
4201         else
4202           qh_memfree (facet->center, qh normal_size);
4203 	facet->center= NULL;
4204       }
4205     }
4206     qh CENTERtype= type;
4207   }
4208   trace2((qh ferr, "clearcenters: switched to center type %d\n", type));
4209 } /* clearcenters */
4210 
4211 /*-------------------------------------------------
4212 -clearnewvertices- clear vertices from newvertex_list
4213 */
qh_clearnewvertices(void)4214 void qh_clearnewvertices (void /*qh newvertex_list*/) {
4215   vertexT *vertex;
4216 
4217   FORALLvertex_(qh newvertex_list)
4218     vertex->newlist= False;
4219   qh newvertex_list= NULL;
4220 } /* clearnewvertices */
4221 
4222 /*-------------------------------------------------
4223 -clearvisible- clear facets from visible list
4224   resets NEWfacets
4225 */
qh_clearvisible(void)4226 void qh_clearvisible (void /*qh visible_list*/) {
4227   facetT *visible;
4228 
4229   FORALLvisible_facets
4230     visible->visible= False;
4231   qh num_visible= 0;
4232   qh visible_list= NULL;
4233   qh NEWfacets= False;
4234 } /* clearvisible */
4235 
4236 /*----------------------------------------
4237 -createsimplex- creates a simplex from a set of vertices
4238 returns:
4239     initializes qh facet_list to the simplex
4240 */
qh_createsimplex(setT * vertices)4241 void qh_createsimplex(setT *vertices) {
4242   facetT *facet= NULL, *newfacet;
4243   boolT toporient= True;
4244   int vertex_i, vertex_n, nth, tempint;
4245   setT *newfacets= qh_settemp (qh hull_dim+1);
4246   vertexT *vertex;
4247 
4248   qh facet_list= qh newfacet_list= qh facet_tail= qh_newfacet();
4249   qh vertex_list= qh newvertex_list= qh vertex_tail= qh_newvertex(NULL);
4250   FOREACHvertex_i_(vertices) {
4251     newfacet= qh_newfacet();
4252     newfacet->vertices= qh_setnew_delnthsorted (vertices, vertex_n,
4253 						vertex_i, 0);
4254     newfacet->toporient= toporient;
4255     qh_appendfacet(newfacet);
4256     qh_appendvertex (vertex);
4257     qh_setappend (&newfacets, newfacet);
4258     tempint = (int)toporient;
4259     tempint ^= True;
4260     toporient = (boolT)tempint;
4261   }
4262   FORALLnew_facets {
4263     nth= 0;
4264     FORALLfacet_(qh newfacet_list) {
4265       if (facet != newfacet)
4266         SETelem_(newfacet->neighbors, nth++)= facet;
4267     }
4268     qh_settruncate (newfacet->neighbors, qh hull_dim);
4269   }
4270   qh_settempfree (&newfacets);
4271   trace1((qh ferr, "qh_createsimplex: created simplex\n"));
4272 } /* createsimplex */
4273 
4274 
4275 /*-------------------------------------------------
4276 -deletevisible- delete visible facets
4277     ridges and vertices already deleted
4278     horizon facets do not reference facets on qh visible_list
4279     new facets in qh newfacet_list
4280 returns:
4281     deletes each facet and removes from facetlist
4282     calls qh_clearvisible()
4283     uses qh visit_id;
4284 */
qh_deletevisible()4285 void qh_deletevisible (/*qh visible_list*/) {
4286   facetT *visible, *nextfacet;
4287   vertexT *vertex, **vertexp;
4288   int numvisible= 0;
4289 
4290   trace1((qh ferr, "qh_deletevisible: delete visible facets\n"));
4291   for (visible= qh visible_list; visible && visible->visible;
4292                 visible= nextfacet) { /* deleting current */
4293     nextfacet= visible->next;
4294     numvisible++;
4295     qh_delfacet(visible);
4296   }
4297 
4298   if (numvisible != qh num_visible) qhull_fatal(48);
4299 
4300   FOREACHvertex_(qh del_vertices)
4301     qh_delvertex (vertex);
4302   qh_settruncate (qh del_vertices, 0);
4303   qh_clearvisible();
4304 } /* deletevisible */
4305 
4306 
4307 /*-------------------------------------------------
4308 -delfacet- removes facet from facet_list and frees up its memory
4309    assumes vertices and ridges already freed
4310 */
qh_delfacet(facetT * facet)4311 void qh_delfacet(facetT *facet) {
4312   void **freelistp;
4313 
4314   trace5((qh ferr, "qh_delfacet: delete f%d\n", facet->id));
4315   if (facet == qh tracefacet)
4316     qh tracefacet= NULL;
4317   qh_removefacet(facet);
4318   qh_memfree_(facet->normal, qh normal_size, freelistp);
4319   if (qh CENTERtype == qh_voronoi) {
4320     qh_memfree_(facet->center, qh center_size, freelistp);
4321   }else {
4322     qh_memfree_(facet->center, qh normal_size, freelistp);
4323   }
4324   qh_setfree(&(facet->neighbors));
4325   if (facet->ridges)
4326     qh_setfree(&(facet->ridges));
4327   qh_setfree(&(facet->vertices));
4328   if (facet->outsideset)
4329     qh_setfree(&(facet->outsideset));
4330   if (facet->coplanarset)
4331     qh_setfree(&(facet->coplanarset));
4332   qh_memfree_(facet, sizeof(facetT), freelistp);
4333 } /* delfacet */
4334 
4335 
4336 /*-------------------------------------------------
4337 -delridge- deletes ridge from data structures it belongs to and frees up the
4338 memory occupied by it
4339 notes:
4340   in merge.c, caller sets vertex->delridge for each vertex
4341   also freed in qh_freeqhull
4342 */
qh_delridge(ridgeT * ridge)4343 void qh_delridge(ridgeT *ridge) {
4344   void **freelistp;
4345 
4346   qh_setdel(ridge->top->ridges, ridge);
4347   qh_setdel(ridge->bottom->ridges, ridge);
4348   qh_setfree(&(ridge->vertices));
4349   qh_memfree_(ridge, sizeof(ridgeT), freelistp);
4350 } /* delridge */
4351 
4352 
4353 /*-------------------------------------------------
4354 -delvertex- deletes a vertex and frees its memory
4355   assumes vertex->adjacencies have been updated if needed
4356   unlinks for vertex_list
4357 */
qh_delvertex(vertexT * vertex)4358 void qh_delvertex (vertexT *vertex) {
4359 
4360   if (vertex == qh tracevertex)
4361     qh tracevertex= NULL;
4362   qh_removevertex (vertex);
4363   qh_setfree (&vertex->neighbors);
4364   qh_memfree(vertex, sizeof(vertexT));
4365 } /* delvertex */
4366 
4367 
4368 /*----------------------------------------
4369 -facet3vertex- return temporary set of 3-d vertices
4370   in qh_ORIENTclock order
4371 */
qh_facet3vertex(facetT * facet)4372 setT *qh_facet3vertex (facetT *facet) {
4373   ridgeT *ridge, *firstridge;
4374   vertexT *vertex;
4375   int cntvertices, cntprojected=0;
4376   setT *vertices;
4377 
4378   cntvertices= qh_setsize(facet->vertices);
4379   vertices= qh_settemp (cntvertices);
4380   if (facet->simplicial) {
4381 
4382     if (cntvertices != 3) qhull_fatal(49);
4383 
4384     qh_setappend (&vertices, SETfirst_(facet->vertices));
4385     if (facet->toporient ^ qh_ORIENTclock)
4386       qh_setappend (&vertices, SETsecond_(facet->vertices));
4387     else
4388       qh_setaddnth (&vertices, 0, SETsecond_(facet->vertices));
4389     qh_setappend (&vertices, SETelem_(facet->vertices, 2));
4390   }else {
4391     ridge= firstridge= (ridgeT *)SETfirst_(facet->ridges);   /* no infinite */
4392     while ((ridge= qh_nextridge3d (ridge, facet, &vertex))) {
4393       qh_setappend (&vertices, vertex);
4394       if (++cntprojected > cntvertices || ridge == firstridge)
4395         break;
4396     }
4397 
4398     if (!ridge || cntprojected != cntvertices) qhull_fatal(50);
4399 
4400   }
4401   return vertices;
4402 } /* facet3vertex */
4403 
4404 
4405 /*-------------------------------------------------
4406 -facetintersect- return vertices for intersection of two simplicial facets
4407   may include 1 prepended entry (if more, need to settemppush)
4408 returns:
4409   returns set of hull_dim-1 + optional extra
4410   returns skipped index for each test and checks for exactly one
4411 notes:
4412   does not need settemp since set in quick memory
4413   see also qh_vertexintersect and qh_vertexintersect_new
4414   use qh_setnew_delnthsorted to get nth ridge (no skip information)
4415 */
qh_facetintersect(facetT * facetA,facetT * facetB,int * skipA,int * skipB,int prepend)4416 setT *qh_facetintersect (facetT *facetA, facetT *facetB,
4417 			 int *skipA,int *skipB, int prepend) {
4418   setT *intersect;
4419   int dim= qh hull_dim, i, j;
4420   facetT **neighborsA, **neighborsB;
4421 
4422   neighborsA= SETaddr_(facetA->neighbors, facetT);
4423   neighborsB= SETaddr_(facetB->neighbors, facetT);
4424   i= j= 0;
4425   if (facetB == *neighborsA++)
4426     *skipA= 0;
4427   else if (facetB == *neighborsA++)
4428     *skipA= 1;
4429   else if (facetB == *neighborsA++)
4430     *skipA= 2;
4431   else {
4432     for (i= 3; i < dim; i++) {
4433       if (facetB == *neighborsA++) {
4434         *skipA= i;
4435         break;
4436       }
4437     }
4438   }
4439   if (facetA == *neighborsB++)
4440     *skipB= 0;
4441   else if (facetA == *neighborsB++)
4442     *skipB= 1;
4443   else if (facetA == *neighborsB++)
4444     *skipB= 2;
4445   else {
4446     for (j= 3; j < dim; j++) {
4447       if (facetA == *neighborsB++) {
4448         *skipB= j;
4449         break;
4450       }
4451     }
4452   }
4453 
4454   if (i >= dim || j >= dim) qhull_fatal(51);
4455 
4456   intersect= qh_setnew_delnthsorted (facetA->vertices, qh hull_dim, *skipA, prepend);
4457   trace4((qh ferr, "qh_facetintersect: f%d skip %d matches f%d skip %d\n",
4458 	  facetA->id, *skipA, facetB->id, *skipB));
4459   return(intersect);
4460 } /* facetintersect */
4461 
4462 
4463 /*----------------------------------------
4464 -gethash- return hashvalue for a set with firstindex and skipelem
4465   assumes at least firstindex+1 elements
4466   sum of elements does badly in high d
4467   assumes skipelem is NULL, in set, or part of hash
4468 */
qh_gethash(int hashsize,setT * set,int size,int firstindex,void * skipelem)4469 unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem) {
4470   void **elemp= SETelemaddr_(set, firstindex, void);
4471   unsigned hash, elem;
4472   int i;
4473 
4474   switch (size-firstindex) {
4475   case 1:
4476     hash= (unsigned long)(*elemp) - (unsigned long) skipelem;
4477     break;
4478   case 2:
4479     hash= (unsigned long)(*elemp) + (unsigned long)elemp[1] - (unsigned long) skipelem;
4480     break;
4481   case 3:
4482     hash= (unsigned long)(*elemp) + (unsigned long)elemp[1] + (unsigned long)elemp[2]
4483       - (unsigned long) skipelem;
4484     break;
4485   case 4:
4486     hash= (unsigned long)(*elemp) + (unsigned long)elemp[1] + (unsigned long)elemp[2]
4487       + (unsigned long)elemp[3] - (unsigned long) skipelem;
4488     break;
4489   case 5:
4490     hash= (unsigned long)(*elemp) + (unsigned long)elemp[1] + (unsigned long)elemp[2]
4491       + (unsigned long)elemp[3] + (unsigned long)elemp[4] - (unsigned long) skipelem;
4492     break;
4493   case 6:
4494     hash= (unsigned long)(*elemp) + (unsigned long)elemp[1] + (unsigned long)elemp[2]
4495       + (unsigned long)elemp[3] + (unsigned long)elemp[4]+ (unsigned long)elemp[5]
4496       - (unsigned long) skipelem;
4497     break;
4498   default:
4499     hash= 0;
4500     i= 3;
4501     do {     /* this is about 10% in 10-d */
4502       if ((elem= (unsigned long)*elemp++) != (unsigned long)skipelem) {
4503         hash ^= (elem << i) + (elem >> (32-i));
4504 	i += 3;
4505 	if (i >= 32)
4506 	  i -= 32;
4507       }
4508     }while(*elemp);
4509     break;
4510   }
4511   hash %= (unsigned) hashsize;
4512   /* hash= 0;   for debugging purposes */
4513   return hash;
4514 } /* gethash */
4515 
4516 /*-------------------------------------------------
4517 -isvertex- returns vertex if point is in vertex set, else returns NULL
4518 */
qh_isvertex(pointT * point,setT * vertices)4519 vertexT *qh_isvertex (pointT *point, setT *vertices) {
4520   vertexT *vertex, **vertexp;
4521 
4522   FOREACHvertex_(vertices) {
4523     if (vertex->point == point)
4524       return vertex;
4525   }
4526   return NULL;
4527 } /* isvertex */
4528 
4529 
4530 /*-------------------------------------------------
4531 -makenewfacet- creates a toporient? facet from vertices and apex
4532    modifies vertices
4533 returns:
4534     adds newfacet to qh facet_list
4535        facet->neighbor= horizon, but not vice versa
4536     facet->vertices= vertices= apex+vertices
4537     facet->hyperplane defined
4538     newvertex_list updated
4539 */
qh_makenewfacet(setT * vertices,boolT toporient,facetT * horizon)4540 facetT *qh_makenewfacet(setT *vertices, boolT toporient,facetT *horizon) {
4541   facetT *newfacet;
4542   vertexT *vertex, **vertexp;
4543 
4544   FOREACHvertex_(vertices) {
4545     if (!vertex->newlist) {
4546       vertex->newlist= True;
4547       qh_removevertex (vertex);
4548       qh_appendvertex (vertex);
4549     }
4550   }
4551   newfacet= qh_newfacet();
4552   newfacet->vertices= vertices;
4553   newfacet->toporient= toporient;
4554   qh_setfacetplane (newfacet);
4555   qh_setappend(&(newfacet->neighbors), horizon);
4556   qh_appendfacet(newfacet);
4557   return(newfacet);
4558 } /* makenewfacet */
4559 
4560 
4561 /*-------------------------------------------------
4562 -makenewfacets- make new facets from point and qh visible_list
4563 returns:
4564   qh newfacet_list= list of new facets with hyperplanes and id >= newfacet_id
4565   qh newvertex_list= list of vertices in new facets with 'new' set
4566   if (qh ONLYgood)
4567     newfacets reference horizon facets, but not vice versa
4568     ridges reference non-simplicial horizon ridges, but not vice versa
4569     does not change existing facets
4570   otherwise
4571     newfacets attached to horizon facets and ridges
4572     first neighbor of visible facet is corresponding new facet
4573 */
qh_makenewfacets(pointT * point)4574 vertexT *qh_makenewfacets (pointT *point /*visible_list*/) {
4575   facetT *visible, *newfacet= NULL, *newfacet2= NULL, *neighbor, **neighborp;
4576   vertexT *apex;
4577   int numnew=0;
4578 
4579   qh newfacet_list= qh facet_tail;
4580   qh newvertex_list= qh vertex_tail;
4581   qh newfacet_id= qh facet_id;
4582   apex= qh_newvertex(point);
4583   apex->newlist= True;
4584   qh_appendvertex (apex);
4585   qh visit_id++;
4586   if (!qh ONLYgood)
4587     qh NEWfacets= True;
4588   FORALLvisible_facets {
4589     FOREACHneighbor_(visible)
4590       neighbor->seen= False;
4591     if (visible->ridges) {
4592       visible->visitid= qh visit_id;
4593       newfacet2= qh_makenew_nonsimplicial (visible, apex, &numnew);
4594     }
4595     if (visible->simplicial)
4596       newfacet= qh_makenew_simplicial (visible, apex, &numnew);
4597     if (!qh ONLYgood) {
4598       if (newfacet2)
4599         newfacet= newfacet2;
4600       if (!newfacet)
4601         zinc_(Zinsidevisible);
4602       SETfirst_(visible->neighbors)= newfacet;
4603       SETsecond_(visible->neighbors)= NULL;
4604     }
4605   }
4606   trace1((qh ferr, "qh_makenewfacets: created %d new facets from point p%d to horizon\n",
4607 	  numnew, qh_pointid(point)));
4608 
4609   /*
4610   if (qh IStracing >= 4)
4611     qh_printfacetlist (qh newfacet_list, NULL, qh_ALL);
4612     THIS IS NO LONGER IN SERVICE */
4613 
4614   return apex;
4615 } /* makenewfacets */
4616 
4617 /*---------------------------------------------
4618 -makenew_nonsimplicial- make new facets for ridges of visible facets
4619   qh visit_id if visible has already been seen
4620   attaches new facets if !qh ONLY good
4621   assumes all 'seen' flags false
4622 returns:
4623   newfacet or NULL, bumps numnew as needed
4624   marks ridge neighbors for simplicial visible
4625   if (qh ONLYgood)
4626     ridges on newfacet, horizon, and visible
4627   else
4628     ridge and neighbors between newfacet and horizon
4629     visible facet's ridges are deleted
4630 */
qh_makenew_nonsimplicial(facetT * visible,vertexT * apex,int * numnew)4631 facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew) {
4632   void **freelistp;
4633   ridgeT *ridge, **ridgep;
4634   facetT *neighbor, *newfacet= NULL;
4635   setT *vertices;
4636   boolT toporient = False;
4637 
4638   FOREACHridge_(visible->ridges) {
4639     neighbor= otherfacet_(ridge, visible);
4640     if (neighbor->visible) {
4641       if (!qh ONLYgood) {
4642         if ((int)neighbor->visitid == qh visit_id) {
4643           qh_setfree (&(ridge->vertices));  /* delete on 2nd visit */
4644 	  qh_memfree_(ridge, sizeof(ridgeT), freelistp);
4645 	}
4646       }
4647     }else {  /* neighbor is an horizon facet */
4648       toporient= (boolT)(ridge->top == visible);
4649       vertices= qh_setnew (qh hull_dim); /* makes sure this is quick */
4650       qh_setappend (&vertices, apex);
4651       qh_setappend_set (&vertices, ridge->vertices);
4652       newfacet= qh_makenewfacet(vertices, toporient, neighbor);
4653       (*numnew)++;
4654       if (qh ONLYgood) {
4655         if (!neighbor->simplicial)
4656  	  qh_setappend(&(newfacet->ridges), ridge);
4657       }else {  /* qh_attachnewfacets */
4658         if (neighbor->seen) {
4659 
4660 	  if (neighbor->simplicial) qhull_fatal(52);
4661 
4662 	  qh_setappend (&(neighbor->neighbors), newfacet);
4663 	}else
4664           qh_setreplace (neighbor->neighbors, visible, newfacet);
4665         if (neighbor->simplicial) {
4666           qh_setdel (neighbor->ridges, ridge);
4667           qh_setfree (&(ridge->vertices));
4668 	  qh_memfree (ridge, sizeof(ridgeT));
4669 	}else {
4670  	  qh_setappend(&(newfacet->ridges), ridge);
4671  	  if (toporient)
4672  	    ridge->top= newfacet;
4673  	  else
4674  	    ridge->bottom= newfacet;
4675  	}
4676       trace4((qh ferr, "qh_makenew_nonsimplicial: created facet f%d from v%d and r%d of horizon f%d\n",
4677 	    newfacet->id, apex->id, ridge->id, neighbor->id));
4678       }
4679     }
4680     neighbor->seen= True;
4681   } /* for each ridge */
4682   if (!qh ONLYgood)
4683     SETfirst_(visible->ridges)= NULL;
4684   return newfacet;
4685 } /* makenew_nonsimplicial */
4686 
4687 /*---------------------------------------------
4688 -makenew_simplicial- make new facets for simplicial facet
4689   uses 'seen' flag
4690   attaches new facets if !qh ONLY good
4691 returns:
4692   newfacet or NULL, bumps numnew as needed
4693   if (!qh ONLYgood)
4694     neighbors between newfacet and horizon
4695 */
qh_makenew_simplicial(facetT * visible,vertexT * apex,int * numnew)4696 facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew) {
4697   facetT *neighbor, **neighborp, *newfacet= NULL;
4698   setT *vertices;
4699   boolT flip, toporient;
4700   int horizonskip, visibleskip;
4701 
4702   FOREACHneighbor_(visible) {
4703     if (!neighbor->seen && !neighbor->visible) {
4704       vertices= qh_facetintersect(neighbor,visible, &horizonskip, &visibleskip, 1);
4705       SETfirst_(vertices)= apex;
4706       flip= (boolT) ((horizonskip & 0x1) ^ (visibleskip & 0x1));
4707       toporient=(boolT)( neighbor->toporient ^ !(horizonskip & 0x1) );
4708       newfacet= qh_makenewfacet(vertices, toporient, neighbor);
4709       (*numnew)++;
4710       if (!qh ONLYgood)
4711         SETelem_(neighbor->neighbors, horizonskip)= newfacet;
4712       trace4((qh ferr, "qh_makenew_simplicial: create facet f%d top %d from v%d and horizon f%d skip %d top %d and visible f%d skip %d, flip? %d\n",
4713 	    newfacet->id, toporient, apex->id, neighbor->id, horizonskip,
4714 	      neighbor->toporient, visible->id, visibleskip, flip));
4715     }
4716   }
4717   return newfacet;
4718 } /* makenew_simplicial */
4719 
4720 /*-------------------------------------------------
4721 -matchduplicate- try to match an unmatched duplicated ridge
4722 returns:
4723   True if a match was made
4724 notes:
4725   found matching facet for a duplicate ridge.
4726      1) if keep already found, merge this pair
4727      2) if !flip&!flip, keep this
4728      3) if flip & flip, merge this pair
4729      4) otherwise, return False and continue
4730 */
qh_matchduplicate(facetT * facet,int skip,facetT * newfacet,int newskip,boolT keepfound)4731 boolT qh_matchduplicate (facetT *facet, int skip, facetT *newfacet, int newskip, boolT keepfound) {
4732   boolT ismatched= False;
4733 
4734   trace2((qh ferr, "qh_matchduplicate: duplicated f%d skip %d matches new f%d skip %d.  ",
4735            facet->id, skip, newfacet->id, newskip));
4736   if (keepfound) {
4737     SETelem_(facet->neighbors, skip)= newfacet;
4738     if (qh PREmerge)
4739       SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
4740     else
4741       SETelem_(newfacet->neighbors, newskip)= facet;
4742     trace2((qh ferr, "Merge this pair.\n"));
4743     ismatched= True;
4744   }else if (!facet->flipped && !newfacet->flipped) {
4745     SETelem_(facet->neighbors, skip)= newfacet;
4746     SETelem_(newfacet->neighbors, newskip)= facet;
4747     trace2((qh ferr, "Match good pair\n"));
4748     ismatched= True;
4749   }else if (facet->flipped && newfacet->flipped) {
4750     SETelem_(facet->neighbors, skip)= newfacet;
4751     if (qh PREmerge)
4752       SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
4753     else
4754       SETelem_(newfacet->neighbors, newskip)= facet;
4755     trace2((qh ferr, "Merge flipped pair\n"));
4756     ismatched= True;
4757   }else
4758     trace2((qh ferr, "No match, continue\n"));
4759   if (qh IStracing >= 4) {
4760 
4761     /*
4762     qh_errprint ("OLD/NEW", facet, newfacet, NULL, NULL);
4763     NO LONGER IN SERVICE */
4764 
4765     qh_setprint (qh ferr, "facet's neighbors", facet->neighbors);
4766     qh_setprint (qh ferr, "newfacet's", newfacet->neighbors);
4767   }
4768   return ismatched;
4769 } /* matchduplicate */
4770 
4771 /*--------------------------------------------
4772 -matchmatch- try to match duplicate matching pair and newfacet
4773 returns:
4774   True if existing match is ok and continue with newfacet
4775   False if need to place matchfacet
4776     newmatched set if newfacet matched
4777 notes:
4778   1) if pair is !flip&!flip, keep is found and continue
4779   2) if pair is flip&flip, merge them and continue
4780   3) otherwise, replace matchfacet
4781        if new pair is !flip&!flip, keep is found
4782        if new pair is flip&flip, merge them
4783        otherwise, mark duplicated and continue
4784 */
qh_matchmatch(facetT * facet,int skip,facetT * matchfacet,facetT * newfacet,int newskip,boolT ismatch,boolT * keepfound,boolT * newmatched)4785 boolT qh_matchmatch (facetT *facet, int skip, facetT *matchfacet, facetT *newfacet,
4786      int newskip, boolT ismatch, boolT *keepfound, boolT *newmatched) {
4787   int matchskip;
4788   boolT ismatched= False;
4789 
4790   matchskip= qh_setindex (matchfacet->neighbors, facet);
4791   trace2((qh ferr, "qh_matchmatch: duplicated f%d skip %d matches f%d skip %d and new f%d skip %d.  ",
4792     facet->id, skip, matchfacet->id, matchskip, newfacet->id, newskip));
4793   if (!facet->flipped && !matchfacet->flipped) {
4794     *keepfound= True;
4795     trace2((qh ferr, "Keep good match\n"));
4796     ismatched= True;
4797   }else if (facet->flipped && matchfacet->flipped) {
4798     if (matchskip >= 0 && qh PREmerge)
4799       SETelem_(matchfacet->neighbors, matchskip)= qh_MERGEridge;
4800     trace2((qh ferr, "Both flipped, merge\n"));
4801     ismatched= True;
4802   }else {
4803     /* matched facets have opposite orientations, undo matchfacet */
4804     SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge;
4805     if (ismatch && (facet->flipped == newfacet->flipped)) {
4806       SETelem_(facet->neighbors, skip)= newfacet;
4807       if (newfacet->flipped && qh PREmerge)
4808 	SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
4809       else
4810 	SETelem_(newfacet->neighbors, newskip)= facet;
4811       trace2((qh ferr, "Substitute new\n"));
4812       *newmatched= True;
4813     }else {
4814       SETelem_(facet->neighbors, skip)= qh_DUPLICATEridge;
4815       *newmatched= False;
4816       trace2((qh ferr, "Undo match\n"));
4817     }
4818   }
4819   if (qh IStracing >= 4) {
4820 
4821     /*
4822     qh_errprint ("OLD/MATCH", facet, matchfacet, NULL, NULL);
4823     qh_errprint ("NEW", newfacet, NULL, NULL, NULL);
4824     NO LONGER IN SERVICE */
4825 
4826     qh_setprint (qh ferr, "facet's neighbors", facet->neighbors);
4827     qh_setprint (qh ferr, "matchfacet's", matchfacet->neighbors);
4828     qh_setprint (qh ferr, "newfacet's", newfacet->neighbors);
4829   }
4830   return ismatched;
4831 } /* qh_matchmatch */
4832 
4833 /*-------------------------------------------------
4834 -matchneighbor- match subridge of newfacet with neighbor or add to hash_table
4835   ridge is newfacet->vertices w/o newskip vertex
4836   flipped tested if PREmerge or FORCEoutput
4837   use matchall to match unmatched duplicates
4838 returns:
4839   at end of matching duplicate ridges,
4840     one !flipped,!flipped matched
4841     flipped,flipped matched with MERGEridge back pointers
4842     rest are unmatched, with a DUPLICATEridge link
4843     all facets involved have seen set and flip tested
4844 notes:
4845   do not allocate memory (need to free hash_table cleanly)
4846   matches flipped,flipped since these get merged anyway
4847   uses linear hash chains
4848 */
qh_matchneighbor(facetT * newfacet,int newskip,int hashsize,int * hashcount,boolT matchall)4849 void qh_matchneighbor (facetT *newfacet, int newskip, int hashsize, int *hashcount, boolT matchall) {
4850   boolT keepfound= False;  /* True, if !flip,!flip duplicate ridge found */
4851   boolT duplicated= False; /* True, if duplicate ridge detected */
4852   boolT newfound= False;   /* True, if new facet is already in hash chain */
4853   boolT same, ismatch, newmatched;
4854   unsigned hash, scan;
4855   facetT *facet, *matchfacet;
4856   int skip;
4857 
4858   hash= qh_gethash (hashsize, newfacet->vertices, qh hull_dim, 1,
4859                      SETelem_(newfacet->vertices, newskip));
4860   trace4((qh ferr, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n",
4861 	  newfacet->id, newskip, hash, *hashcount));
4862   zinc_(Zhashlookup);
4863   while ((facet= (facetT *)SETelem_(qh hash_table, hash))) {
4864     if (facet == newfacet) {
4865       newfound= True;
4866       goto LABELnexthash;
4867     }
4868     zinc_(Zhashtests);
4869     if (qh_matchvertices (1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
4870 
4871       if (SETelem_(newfacet->vertices, newskip) ==
4872           SETelem_(facet->vertices, skip))
4873 	qhull_fatal(53);
4874 
4875       ismatch=
4876 	(boolT) (same == (int)(newfacet->toporient ^ facet->toporient));
4877       matchfacet= (facetT *)SETelem_(facet->neighbors, skip);
4878       if (matchfacet == qh_MERGEridge)
4879         goto LABELnexthash;
4880       else if (matchfacet == qh_DUPLICATEridge) {
4881         duplicated= True;
4882         matchfacet= NULL;
4883       }else if (ismatch && !matchfacet && !duplicated) {
4884         SETelem_(facet->neighbors, skip)= newfacet;
4885         SETelem_(newfacet->neighbors, newskip)= facet;
4886         (*hashcount)--;
4887         trace4((qh ferr, "qh_matchneighbor: f%d skip %d matched with new f%d skip %d\n",
4888            facet->id, skip, newfacet->id, newskip));
4889         return;
4890       }
4891 
4892       if (!qh PREmerge) qhull_fatal(54);
4893 
4894       if (matchall) {
4895 	if (matchfacet || !ismatch)
4896 	  goto LABELnexthash;
4897 	SETelem_(facet->neighbors, skip)= newfacet;
4898 	SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
4899 	/* this may merge one more ridge than necessary, but hard to detect */
4900 	(*hashcount) -= 2;  /* removed two unmatched facets */
4901         zzinc_(Zmultiflip);
4902 	trace2((qh ferr, "qh_matchneighbor: duplicate f%d skip %d matched with new f%d skip %d\n",
4903              facet->id, skip, newfacet->id, newskip));
4904 	return;
4905       }
4906       duplicated= True;
4907       newfacet->seen= True;
4908       facet->seen= True;
4909       if (matchfacet)
4910         matchfacet->seen= True;
4911       if (!matchfacet && ismatch) {
4912         if (qh_matchduplicate (facet, skip, newfacet, newskip, keepfound)) {
4913           zzinc_(Zmultimatch);
4914           (*hashcount)--;
4915           return;
4916         }
4917       }else if (matchfacet && !keepfound) {
4918         if (!qh_matchmatch (facet, skip, matchfacet, newfacet, newskip,
4919                    ismatch, &keepfound, &newmatched)) {
4920           scan= hash;
4921           while ((facet= (facetT *)SETelem_(qh hash_table, scan))) {
4922             if (facet == matchfacet)
4923               break;
4924             if ((int)(++scan) >= hashsize)
4925               scan= 0;
4926           }
4927           if (!facet)
4928             SETelem_(qh hash_table, scan)= matchfacet;
4929 	  (*hashcount)++;
4930           if (newmatched)
4931             return;
4932           else
4933             (*hashcount)++;
4934         }
4935       }
4936     }
4937 LABELnexthash:
4938     if ((int)(++hash) >= hashsize)
4939       hash= 0;
4940   /* loop terminates because qh_HASHfactor >= 1.1 by qh_initbuffers */
4941   }
4942   (*hashcount)++;
4943   if (!newfound)
4944     SETelem_(qh hash_table, hash)= newfacet;
4945   if (duplicated) {
4946     SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge;
4947     trace4((qh ferr, "qh_matchneighbor: no match for duplicated f%d skip %d at hash %d\n",
4948            newfacet->id, newskip, hash));
4949   }else
4950     trace4((qh ferr, "qh_matchneighbor: no match for f%d skip %d at hash %d\n",
4951            newfacet->id, newskip, hash));
4952 } /* matchneighbor */
4953 
4954 
4955 /*-------------------------------------------------
4956 -matchnewfacets- match newfacets in qh newfacet_list to their newfacet neighbors
4957   newfacets already have neighbor[0] (horizon facet)
4958   assumes qh hash_table is NULL
4959 returns:
4960   qh newfacet_list with full neighbor sets
4961     get vertices with nth neighbor by deleting nth vertex
4962   if PREmerge or FORCEoutput
4963     all facets check for flipped (also prevents point partitioning)
4964   if duplicate ridges and PREmerge
4965     facet->seen set
4966     missing neighbor links identifies extra ridges to be merging
4967 notes:
4968   do not allocate memory after hash_table (need to free it cleanly)
4969 */
qh_matchnewfacets(void)4970 void qh_matchnewfacets (void) {
4971   int numnew=0, numfree= 0, hashcount=0, newskip, nth=0;
4972   facetT *newfacet, *neighbor, **neighborp, *facet;
4973   int facet_i, facet_n, dim= qh hull_dim, hashsize;
4974   setT *neighbors;
4975 
4976   trace1((qh ferr, "qh_matchnewfacets: match neighbors for new facets.\n"));
4977   FORALLnew_facets {
4978     numnew++;
4979     {  /* qh_setzero (newfacet->neighbors, 1, qh hull_dim); */
4980       neighbors= newfacet->neighbors;
4981       // This (void *) cast was in the original, 1990s, pre-64-bit Pelican
4982       neighbors->e[neighbors->maxsize]= reinterpret_cast<void *>(dim+1); /*may be overwritten*/
4983       memset ((char *)&neighbors->e[1], 0, dim * sizeof(void *));
4984     }
4985     if (qh MERGING)
4986       qh_checkflipped (newfacet, NULL, qh_ALL);
4987   }
4988   if (qh FORCEoutput && !qh MERGING)
4989     qh_checkflipped_all (qh newfacet_list);  /* prints warnings for flipped */
4990   qh_newhashtable (numnew*(qh hull_dim-1)); /* twice what is normally needed,
4991                                      but every ridge could be DUPLICATEridge */
4992   hashsize= qh_setsize (qh hash_table);
4993   FORALLnew_facets {
4994     newfacet->seen= False;
4995     for (newskip=1; newskip<qh hull_dim; newskip++) /* furthest/horizon already matched */
4996       qh_matchneighbor (newfacet, newskip, hashsize, &hashcount,
4997 			(boolT)!qh_ALL);
4998 #if 0   /* use the following to trap hashcount errors */
4999     {
5000       int count= 0, k;
5001       facetT *facet, *neighbor;
5002 
5003       count= 0;
5004       FORALLfacet_(qh newfacet_list) {  /* newfacet already in use */
5005 	for (k=1; k<qh hull_dim; k++) {
5006 	  neighbor= SETelem_(facet->neighbors, k);
5007 	  if (!neighbor || neighbor == qh_DUPLICATEridge)
5008 	    count++;
5009 	}
5010 	if (facet == newfacet)
5011 	  break;
5012       }
5013 
5014       if (count != hashcount) qhull_fatal(55);
5015 
5016     }
5017 #endif  /* end of trap code */
5018   }
5019   if (hashcount) {
5020     FORALLnew_facets {
5021       if (newfacet->seen) {
5022         nth= 0;
5023         FOREACHneighbor_(newfacet) {
5024           if (neighbor == qh_DUPLICATEridge) {
5025 	    trace2((qh ferr, "qh_matchnewfacets: find good/flip match for duplicated f%d skip %d\n",
5026 		    newfacet->id, nth));
5027             qh_matchneighbor (newfacet, nth, hashsize, &hashcount, qh_ALL);
5028 
5029 	    /*
5030 	    if (qh IStracing >= 4)
5031 	      qh_errprint ("DUPLICATED/MATCH", newfacet,
5032 		  (facetT*)SETelem_(newfacet->neighbors, nth), NULL, NULL);
5033 	    NO LONGER IN SERVICE */
5034          	    /* this may report MERGEfacet */
5035 	  }
5036           nth++;
5037         }
5038       }
5039     }
5040   }
5041 
5042   if (hashcount) qhull_fatal(56);
5043 
5044   if (qh IStracing >= 2) {
5045     FOREACHfacet_i_(qh hash_table) {
5046       if (!facet)
5047         numfree++;
5048     }
5049     fprintf (qh ferr, "qh_matchnewfacets: %d new facets, %d unused hash entries .  hashsize %d\n",
5050 	     numnew, numfree, qh_setsize (qh hash_table));
5051   }
5052   qh_setfree (&qh hash_table);
5053 
5054   /*
5055   if (qh IStracing >= 4 && qh PREmerge)
5056     qh_printfacetlist (qh newfacet_list, NULL, qh_ALL);
5057     THIS IS NO LONGER IN SERVICE */
5058 
5059 } /* matchnewfacets */
5060 
5061 
5062 /*----------------------------------------
5063 -matchvertices- tests whether vertices match with a single skip
5064   starts match at firstindex since all new facets have a common vertex
5065   assumes skipA is in A and both sets are the same size
5066 returns:
5067   skip index
5068   sets same iff vertices have the same orientation
5069 */
qh_matchvertices(int firstindex,setT * verticesA,int skipA,setT * verticesB,int * skipB,boolT * same)5070 boolT qh_matchvertices (int firstindex, setT *verticesA, int skipA,
5071        setT *verticesB, int *skipB, boolT *same) {
5072   vertexT **elemAp, **elemBp, **skipBp=NULL, **skipAp;
5073 
5074   elemAp= SETelemaddr_(verticesA, firstindex, vertexT);
5075   elemBp= SETelemaddr_(verticesB, firstindex, vertexT);
5076   skipAp= SETelemaddr_(verticesA, skipA, vertexT);
5077   do if (elemAp != skipAp) {
5078     while (*elemAp != *elemBp++) {
5079       if (skipBp)
5080         return False;
5081       skipBp= elemBp;  /* one extra like FOREACH */
5082     }
5083   }while(*(++elemAp));
5084   if (!skipBp)
5085     skipBp= ++elemBp;
5086   *skipB= (int)SETindex_(verticesB, skipB);
5087   *same= (boolT)(!(((unsigned)skipA & 0x1) ^ ((unsigned)*skipB & 0x1)));
5088   trace4((qh ferr, "qh_matchvertices: matched by skip %d (v%d) and skip %d (v%d) same? %d\n",
5089 	  skipA, (*skipAp)->id, *skipB, (*(skipBp-1))->id, *same));
5090   return (True);
5091 } /* matchvertices */
5092 
5093 /*----------------------------------------
5094 -nextridge3d- return next ridge and vertex for a 3d facet
5095   in qh_ORIENTclock order
5096   n^2 implementation to trace all ridges
5097   be sure to stop on any 2nd visit
5098 */
qh_nextridge3d(ridgeT * atridge,facetT * facet,vertexT ** vertexp)5099 ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp) {
5100   vertexT *atvertex, *vertex, *othervertex;
5101   ridgeT *ridge, **ridgep;
5102 
5103   if ((atridge->top == facet) ^ qh_ORIENTclock)
5104     atvertex= (vertexT *)SETsecond_(atridge->vertices);
5105   else
5106     atvertex= (vertexT *)SETfirst_(atridge->vertices);
5107   FOREACHridge_(facet->ridges) {
5108     if (ridge == atridge)
5109       continue;
5110     if ((ridge->top == facet) ^ qh_ORIENTclock) {
5111       othervertex= (vertexT *)SETsecond_(ridge->vertices);
5112       vertex= (vertexT *)SETfirst_(ridge->vertices);
5113     }else {
5114       vertex= (vertexT *)SETsecond_(ridge->vertices);
5115       othervertex= (vertexT *)SETfirst_(ridge->vertices);
5116     }
5117     if (vertex == atvertex) {
5118       if (vertexp)
5119         *vertexp= othervertex;
5120       return ridge;
5121     }
5122   }
5123   return NULL;
5124 } /* nextridge3d */
5125 
5126 
5127 /*----------------------------------------
5128 -newfacet- creates and allocates space for a facet
5129 returns:
5130     all fields initialized or cleared (NULL)
5131     preallocates neighbors
5132 */
qh_newfacet(void)5133 facetT *qh_newfacet(void) {
5134   facetT *facet = NULL;
5135   void **freelistp;
5136 
5137   facetT_qh_memalloc_(sizeof(facetT), freelistp, facet);
5138   memset ((char *)facet, 0, sizeof(facetT));
5139   if (qh facet_id == 0xFFFFFF) {
5140     fprintf(qh ferr, "\
5141 qhull warning: more than %d facets.  Id field overflows and two facets\n\
5142 may have the same identifier.  Otherwise output ok.\n", 0xFFFFFF);
5143   }
5144   if (qh facet_id == (int)qh tracefacet_id)
5145     qh tracefacet= facet;
5146   facet->id= qh facet_id++;
5147   facet->neighbors= qh_setnew(qh hull_dim);
5148 #if !qh_COMPUTEfurthest
5149   facet->furthestdist= 0.0;
5150 #endif
5151 #if qh_MAXoutside
5152   if (qh FORCEoutput && qh APPROXhull)
5153     facet->maxoutside= qh MINoutside;
5154   else
5155     facet->maxoutside= qh DISTround;
5156 #endif
5157   facet->simplicial= True;
5158   facet->good= True;
5159   trace4((qh ferr, "qh_newfacet: created facet f%d\n", facet->id));
5160   return (facet);
5161 } /* newfacet */
5162 
5163 
5164 /*-------------------------------------------------
5165 -newhashtable- returns size of qh hash_table of at least newsize slots
5166   assumes qh hash_table is NULL
5167   qh_HASHfactor determines the number of extra slots
5168 */
qh_newhashtable(int newsize)5169 int qh_newhashtable(int newsize) {
5170   int size;
5171 
5172   size= ((newsize+1)*qh_HASHfactor) | 0x1;  /* odd number */
5173   while (True) {
5174     if ((size%3) && (size%5))
5175       break;
5176     size += 2;
5177     /* loop terminates because there is an infinite number of primes */
5178   }
5179   qh hash_table= qh_setnew (size);
5180   qh_setzero (qh hash_table, 0, size);
5181   return size;
5182 } /* newhashtable */
5183 
5184 /*----------------------------------------
5185 -newridge- creates and allocates space for a ridge
5186 */
qh_newridge(void)5187 ridgeT *qh_newridge(void) {
5188   ridgeT *ridge = NULL;
5189   void **freelistp;
5190 
5191   ridgeT_qh_memalloc_(sizeof(ridgeT), freelistp, ridge);
5192   memset ((char *)ridge, 0, sizeof(ridgeT));
5193   zinc_(Ztotridges);
5194   if (qh ridge_id == 0xFFFFFF) {
5195     fprintf(qh ferr, "\
5196 qhull warning: more than %d ridges.  Id field overflows and two ridges\n\
5197 may have the same identifier.  Otherwise output ok.\n", 0xFFFFFF);
5198   }
5199   ridge->id= qh ridge_id++;
5200   trace4((qh ferr, "qh_newridge: created ridge r%d\n", ridge->id));
5201   return (ridge);
5202 } /* newridge */
5203 
5204 
5205 /*----------------------------------------
5206 -newvertex- creates and allocates space for a vertex
5207 */
qh_newvertex(pointT * point)5208 vertexT *qh_newvertex(pointT *point) {
5209   vertexT *vertex;
5210 
5211   zinc_(Ztotvertices);
5212   vertex= (vertexT *)qh_memalloc(sizeof(vertexT));
5213   memset ((char *) vertex, 0, sizeof (vertexT));
5214 
5215   if (qh vertex_id == 0xFFFFFF) qhull_fatal(57);
5216 
5217   if (qh vertex_id == qh tracevertex_id)
5218     qh tracevertex= vertex;
5219   vertex->id= qh vertex_id++;
5220   vertex->point= point;
5221   trace4((qh ferr, "qh_newvertex: vertex p%d (v%d) created\n", qh_pointid(vertex->point),
5222 	  vertex->id));
5223   return (vertex);
5224 } /* newvertex */
5225 
5226 /*-------------------------------------------------
5227 -point- return point for a point id, or NULL if unknown
5228 */
qh_point(int id)5229 pointT *qh_point (int id) {
5230 
5231   if (id < 0)
5232     return NULL;
5233   if (id < qh num_points)
5234     return ((pointT *)((unsigned long)qh first_point+(unsigned long)((id)*qh normal_size)));
5235   id -= qh num_points;
5236   if (id < qh_setsize (qh other_points))
5237     return (pointT *)SETelem_(qh other_points, id);
5238   return NULL;
5239 } /* point */
5240 
5241 /*-------------------------------------------------
5242 -point_add- access function for pointfacet and pointvertex
5243 */
qh_point_add(setT * set,pointT * point,void * elem)5244 void qh_point_add (setT *set, pointT *point, void *elem) {
5245   int id;
5246 
5247   if ((id= qh_pointid(point)) == -1)
5248     fprintf (qh ferr,
5249 	     "qhull internal warning (pointfacet,pointvertex): unknown point %p\n",
5250 	     static_cast<void *>(point));
5251   else
5252     SETelem_(set, id)= elem;
5253 } /* point_add */
5254 
5255 
5256 /*-------------------------------------------------
5257 -pointfacet- return temporary set of facets indexed by point id
5258   for vertices, coplanarset, and outsideset
5259   access with FOREACHfacet_i_(facets) and SETelem_(facets, i)
5260   NULL if no facet for point (inside)
5261      this will include qh GOODpointp
5262 */
qh_pointfacet(void)5263 setT *qh_pointfacet (void /*qh facet_list*/) {
5264   int numpoints= qh num_points + qh_setsize (qh other_points);
5265   setT *facets;
5266   facetT *facet;
5267   vertexT *vertex, **vertexp;
5268   pointT *point, **pointp;
5269 
5270   facets= qh_settemp (numpoints);
5271   qh_setzero (facets, 0, numpoints);
5272   qh vertex_visit++;
5273   FORALLfacets {
5274     FOREACHvertex_(facet->vertices) {
5275       if ((int)vertex->visitid != qh vertex_visit) {
5276         vertex->visitid= qh vertex_visit;
5277         qh_point_add (facets, vertex->point, facet);
5278       }
5279     }
5280     FOREACHpoint_(facet->coplanarset)
5281       qh_point_add (facets, point, facet);
5282     FOREACHpoint_(facet->outsideset)
5283       qh_point_add (facets, point, facet);
5284   }
5285   return facets;
5286 } /* pointfacet */
5287 
5288 /*-------------------------------------------------
5289 -pointid- return id for a point, -3 if null, -2 if interior, or -1 if not known
5290 */
qh_pointid(pointT * point)5291 int qh_pointid (pointT *point) {
5292   unsigned id;
5293 
5294   if (!point)
5295     return -3;
5296   id= ((unsigned long) point - (unsigned long) qh first_point)/qh normal_size;
5297   if ((int)id >= qh num_points) {
5298     if (point == qh interior_point)
5299       id= (unsigned int) -2;
5300     else if ((int)(id= qh_setindex (qh other_points, point)) != -1)
5301       id += qh num_points;
5302   }
5303   return (int) id;
5304 } /* pointid */
5305 
5306 /*-------------------------------------------------
5307 -pointvertex- return temporary set of vertices indexed by point id
5308   access with FOREACHvertex_i_(vertices) and SETelem_(vertices, i)
5309   NULL if no vertex for point
5310      this will include qh GOODpointp
5311 */
qh_pointvertex(void)5312 setT *qh_pointvertex (void /*qh facet_list*/) {
5313   int numpoints= qh num_points + qh_setsize (qh other_points);
5314   setT *vertices;
5315   vertexT *vertex;
5316 
5317   vertices= qh_settemp (numpoints);
5318   qh_setzero (vertices, 0, numpoints);
5319   FORALLvertices
5320     qh_point_add (vertices, vertex->point, vertex);
5321   return vertices;
5322 } /* pointvertex */
5323 
5324 
5325 /*-------------------------------------------------
5326 -prependfacet- prepend facet to the start of a facetlist
5327   increments qh numfacets
5328   updates facetlist, qh facet_list, facet_next
5329 notes:
5330   be careful of prepending since it can lose a pointer.
5331   e.g., can lose _next by deleting and then prepending before _next
5332 */
qh_prependfacet(facetT * facet,facetT ** facetlist)5333 void qh_prependfacet(facetT *facet, facetT **facetlist) {
5334   facetT *prevfacet, *list= *facetlist;
5335 
5336 
5337   trace4((qh ferr, "qh_prependfacet: prepend f%d before f%d\n",
5338 	  facet->id, list->id));
5339   prevfacet= list->previous;
5340   facet->previous= prevfacet;
5341   if (prevfacet)
5342     prevfacet->next= facet;
5343   list->previous= facet;
5344   facet->next= *facetlist;
5345   if (qh facet_list == list)  /* this may change *facetlist */
5346     qh facet_list= facet;
5347   if (qh facet_next == list)
5348     qh facet_next= facet;
5349   *facetlist= facet;
5350   qh num_facets++;
5351 } /* prependfacet */
5352 
5353 
5354 /*-----------------------------------------
5355 -printhashtable- print hash table
5356   not in I/O to avoid bringing io.c in
5357 */
qh_printhashtable(FILE * fp)5358 void qh_printhashtable(FILE *fp) {
5359   facetT *facet, *neighbor;
5360   int id, facet_i, facet_n, neighbor_i= 0, neighbor_n= 0;
5361   vertexT *vertex, **vertexp;
5362 
5363   FOREACHfacet_i_(qh hash_table) {
5364     if (facet) {
5365       FOREACHneighbor_i_(facet) {
5366         if (!neighbor || neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge)
5367           break;
5368       }
5369       if (neighbor_i == neighbor_n)
5370         continue;
5371       fprintf (fp, "hash %d f%d ", facet_i, facet->id);
5372       FOREACHvertex_(facet->vertices)
5373         fprintf (fp, "v%d ", vertex->id);
5374       fprintf (fp, "\n neighbors:");
5375       FOREACHneighbor_i_(facet) {
5376 	if (neighbor == qh_MERGEridge)
5377 	  id= -3;
5378 	else if (neighbor == qh_DUPLICATEridge)
5379 	  id= -2;
5380 	else
5381 	  id= getid_(neighbor);
5382         fprintf (fp, " %d", id);
5383       }
5384       fprintf (fp, "\n");
5385     }
5386   }
5387 } /* printhashtable */
5388 
5389 
5390 /*-------------------------------------------------
5391 -printlists- print out facet and vertex list for debugging (without 'f/v' tags)
5392 */
qh_printlists(void)5393 void qh_printlists (void) {
5394   facetT *facet;
5395   vertexT *vertex;
5396 
5397   fprintf (qh ferr, "qh_printlists: facets:");
5398   FORALLfacets
5399     fprintf (qh ferr, " %d", facet->id);
5400   fprintf (qh ferr, "\n  new facets %d visible facets %d next facet for addpoint %d\n  vertices (new %d):",
5401      getid_(qh newfacet_list), getid_(qh visible_list), getid_(qh facet_next),
5402      getid_(qh newvertex_list));
5403   FORALLvertices
5404     fprintf (qh ferr, " %d", vertex->id);
5405   fprintf (qh ferr, "\n");
5406 } /* printlists */
5407 
5408 /*-------------------------------------------------
5409 -removefacet- unlinks facet from qh facet_list,
5410 updates qh facet_list .newfacet_list .facet_next visible_list
5411 
5412 decrements qh num_facets
5413 */
qh_removefacet(facetT * facet)5414 void qh_removefacet(facetT *facet) {
5415   facetT *next= facet->next, *previous= facet->previous;
5416 
5417   if (facet == qh newfacet_list)
5418     qh newfacet_list= next;
5419   if (facet == qh facet_next)
5420     qh facet_next= next;
5421   if (facet == qh visible_list)
5422     qh visible_list= next;
5423   if (previous) {
5424     previous->next= next;
5425     next->previous= previous;
5426   }else {  /* 1st facet in qh facet_list */
5427     qh facet_list= next;
5428     qh facet_list->previous= NULL;
5429   }
5430   qh num_facets--;
5431   trace4((qh ferr, "qh_removefacet: remove f%d from facet_list\n", facet->id));
5432 } /* removefacet */
5433 
5434 
5435 /*-------------------------------------------------
5436 -removevertex- unlinks vertex from qh vertex_list,
5437 updates qh vertex_list .newvertex_list
5438 
5439 decrements qh num_vertices
5440 */
qh_removevertex(vertexT * vertex)5441 void qh_removevertex(vertexT *vertex) {
5442   vertexT *next= vertex->next, *previous= vertex->previous;
5443 
5444   if (vertex == qh newvertex_list)
5445     qh newvertex_list= next;
5446   if (previous) {
5447     previous->next= next;
5448     next->previous= previous;
5449   }else {  /* 1st vertex in qh vertex_list */
5450     qh vertex_list= vertex->next;
5451     qh vertex_list->previous= NULL;
5452   }
5453   qh num_vertices--;
5454   trace4((qh ferr, "qh_removevertex: remove v%d from vertex_list\n", vertex->id));
5455 } /* removevertex */
5456 
5457 
5458 /*-------------------------------------------------
5459 -vertexintersect- intersects two vertex sets (inverse id ordered)
5460   temporary set vertexsetA is replaced by the intersection
5461      must be at top of stack
5462   could overwrite vertexsetA if currently too slow
5463 */
qh_vertexintersect(setT ** vertexsetA,setT * vertexsetB)5464 void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB) {
5465   setT *intersection;
5466 
5467   intersection= qh_vertexintersect_new (*vertexsetA, vertexsetB);
5468   qh_settempfree (vertexsetA);
5469   *vertexsetA= intersection;
5470   qh_settemppush (intersection);
5471 } /* vertexintersect */
5472 
5473 /*-------------------------------------------------
5474 -vertexintersect_new- intersects two vertex sets (inverse id ordered)
5475 returns:
5476   a new set
5477 */
qh_vertexintersect_new(setT * vertexsetA,setT * vertexsetB)5478 setT *qh_vertexintersect_new (setT *vertexsetA,setT *vertexsetB) {
5479   setT *intersection= qh_setnew (qh hull_dim - 1);
5480   vertexT **vertexA= SETaddr_(vertexsetA, vertexT);
5481   vertexT **vertexB= SETaddr_(vertexsetB, vertexT);
5482 
5483   while (*vertexA && *vertexB) {
5484     if (*vertexA  == *vertexB) {
5485       qh_setappend(&intersection, *vertexA);
5486       vertexA++; vertexB++;
5487     }else {
5488       if ((*vertexA)->id > (*vertexB)->id)
5489         vertexA++;
5490       else
5491         vertexB++;
5492     }
5493   }
5494   return intersection;
5495 } /* vertexintersect_new */
5496 
5497 
5498 /*-------------------------------------------
5499 -vertexneighhbors- for each vertex in hull, determine facet neighbors
5500   nop if VERTEXneighbors
5501   assumes all vertex->neighbors are NULL
5502 returns:
5503   sets qh VERTEXneighbors, qh_addpoint() will maintain them
5504 */
qh_vertexneighbors(void)5505 void qh_vertexneighbors (void /*qh facet_list*/) {
5506   facetT *facet;
5507   vertexT *vertex, **vertexp;
5508 
5509   if (qh VERTEXneighbors)
5510     return;
5511   trace1((qh ferr, "qh_vertexneighbors: determing neighboring facets for each vertex\n"));
5512   qh vertex_visit++;
5513   FORALLfacets {
5514     FOREACHvertex_(facet->vertices) {
5515       if ((int)vertex->visitid != qh vertex_visit) {
5516         vertex->visitid= qh vertex_visit;
5517         vertex->neighbors= qh_setnew (qh hull_dim);
5518       }
5519       qh_setappend (&vertex->neighbors, facet);
5520     }
5521   }
5522   qh VERTEXneighbors= True;
5523 } /* vertexneighbors */
5524 
5525 /*-------------------------------------------------
5526 -vertexsubset- returns True if vertexsetA is a subset of vertexsetB, False
5527   otherwise; relies on vertexsets being sorted;
5528 an empty set is a subset of any other set
5529   */
qh_vertexsubset(setT * vertexsetA,setT * vertexsetB)5530 boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB) {
5531   vertexT **vertexA= (vertexT **) SETaddr_(vertexsetA, vertexT);
5532   vertexT **vertexB= (vertexT **) SETaddr_(vertexsetB, vertexT);
5533 
5534   while (True) {
5535     if (!*vertexA)
5536       return True;
5537     if (!*vertexB)
5538       return False;
5539     if ((*vertexA)->id > (*vertexB)->id)
5540       return False;
5541     if (*vertexA  == *vertexB)
5542       vertexA++;
5543     vertexB++;
5544   }
5545 } /* vertexsubset */
5546 
5547 
5548 /*************************************************************************/
5549 /****************** implementation code from merge.c *********************/
5550 /*************************************************************************/
5551 
5552 /* merge.c - merges non-convex facets
5553 
5554    see README and merge.h
5555 
5556    other modules call qh_merge_nonconvex() and facetdegen()
5557    to avoid loading merge.o, redefine them to null procedures (user.c)
5558 
5559    assumes neighbor sets for each vertex (qh VERTEXneighbors)
5560 
5561    assumes qh CENTERtype= centrum
5562 
5563    copyright (c) 1993-1994 The Geometry Center
5564 */
5565 
5566 static int qh_compareangle(const void *p1, const void *p2);
5567 static int qh_comparevisit (const void *p1, const void *p2);
5568 
5569 /*-------------------------------------------------
5570 -appendmergeset- appends an entry to facet_mergeset, angle is optional
5571   all other fields 0
5572 returns:
5573   merge
5574 notes:
5575   see test_appendmerge()
5576 */
qh_appendmergeset(facetT * facet,facetT * neighbor,realT * angle)5577 mergeT *qh_appendmergeset(facetT *facet, facetT *neighbor, realT *angle) {
5578   mergeT *merge;
5579   void **freelistp;
5580 
5581   mergeT_qh_memalloc_(sizeof(mergeT), freelistp, merge);
5582   memset ((char*) merge, 0, sizeof(mergeT));
5583   merge->facet1= facet;
5584   merge->facet2= neighbor;
5585   if (angle)
5586     merge->angle= *angle;
5587   qh_setappend(&(qh facet_mergeset), merge);
5588   return merge;
5589 } /* appendmergeset */
5590 
5591 
5592 /*-------------------------------------------------
5593 -checkridge_boundary- checks that ridges of a facet are boundaryless,
5594   nop if qh hull_dim < 3 or simplicial
5595   may miss a few errors if pinched facets
5596 */
qh_checkridge_boundary(facetT * facet)5597 void qh_checkridge_boundary (facetT *facet) {
5598 #if 0
5599   ridgeT *ridge, **ridgep, *ridgeA, *errridge= NULL;
5600   vertexT *vertex, **vertexp;
5601   int unmatched= 0, matches=0, hashsize, hashslot;
5602 
5603   /* this code doesn't work because hash buckets can coalesce */
5604   if (qh hull_dim < 3 || facet->simplicial)
5605     return;
5606   trace3((qh ferr, "qh_checkridge_boundary: check subridges for f%d\n", facet->id));
5607   hashsize= qh_newhashtable (qh_setsize (facet->ridges));
5608   FOREACHridge_(facet->ridges)
5609     ridge->seen= False;
5610   FOREACHridge_(facet->ridges) {
5611     FOREACHvertex_(ridge->vertices) {
5612       if ((ridgeA= qh_hashridge_find (qh hash_table, hashsize,
5613              ridge, vertex, NULL, &hashslot))) {
5614         matches++;
5615         ridgeA->seen ^= True;
5616       }else {
5617         unmatched++;
5618         ridge->seen ^= True;
5619         if (hashslot != -1)
5620           SETelem_(qh hash_table, hashslot)= ridge;
5621       }
5622     }
5623   }
5624   FOREACHridge_(facet->ridges) {
5625     if (ridge->seen) {
5626       fprintf(qh ferr, "qhull internal error (checkridge_boundary): subridges of r%d in f%d don't match up\n",
5627                ridge->id, facet->id);
5628       errridge= ridge;
5629     }
5630   }
5631 
5632   if (errridge || unmatched > matches || ((matches-unmatched) ^ 0x1))
5633     qhull_fatal(58);
5634 
5635   qh_settempfree (&qh hash_table);
5636 #endif
5637 } /* checkridge_boundary */
5638 
5639 
5640 /*-------------------------------------------------
5641 -compareangle- used by qsort() to order merges by the angle between
5642  them
5643 */
qh_compareangle(const void * p1,const void * p2)5644 static int qh_compareangle(const void *p1, const void *p2) {
5645   mergeT *a= *((mergeT **)p1), *b= *((mergeT **)p2);
5646 
5647   return ((a->angle > b->angle) ? 1 : -1);
5648 } /* compareangle */
5649 
5650 /*-------------------------------------------------
5651 -comparevisit- used by qsort() to order vertices by their visitid
5652 */
qh_comparevisit(const void * p1,const void * p2)5653 static int qh_comparevisit (const void *p1, const void *p2) {
5654   vertexT *a= *((vertexT **)p1), *b= *((vertexT **)p2);
5655 
5656   return (a->visitid - b->visitid);
5657 } /* comparevisit */
5658 
5659 /*------------------------------------------------
5660 -copynonconvex- copy non-convex flag to all ridges between same neighbors
5661 */
qh_copynonconvex(ridgeT * atridge)5662 void qh_copynonconvex (ridgeT *atridge) {
5663   boolT nonconvex = False;
5664   facetT *facet, *otherfacet;
5665   ridgeT *ridge, **ridgep;
5666 
5667   nonconvex= (boolT) atridge->nonconvex;
5668   facet= atridge->top;
5669   otherfacet= atridge->bottom;
5670   FOREACHridge_(facet->ridges) {
5671     if (otherfacet == otherfacet_(ridge, facet))
5672       ridge->nonconvex= nonconvex;
5673   }
5674 } /* copynonconvex */
5675 
5676 /*------------------------------------------------
5677 -degen_redundant_neighbors- append degen. and redundant neighbors to facet_mergeset
5678   also checks current facet for degeneracy
5679   bumps visitid
5680   called for each mergefacet(), merge and statistics occur in merge_nonconvex
5681     redundant facets will be merged before degenerate ones
5682 notes:
5683   a degenerate facet doesn't have enough neighbors
5684   a redundant facet's vertices is a subset of its neighbor's vertices
5685 */
qh_degen_redundant_neighbors(facetT * facet)5686 void qh_degen_redundant_neighbors (facetT *facet) {
5687   vertexT *vertex, **vertexp;
5688   facetT *neighbor, **neighborp;
5689   int size;
5690   realT angledegen= qh_ANGLEdegen, angleredundant= qh_ANGLEredundant;
5691 
5692   trace3((qh ferr, "qh_degen_redundant_neighbors: test neighbors of f%d\n", facet->id));
5693   if ((size= qh_setsize (facet->neighbors)) < qh hull_dim) {
5694     qh_appendmergeset (facet, facet, &angledegen);
5695     trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate.\n", facet->id));
5696   }
5697   FOREACHneighbor_(facet) {   /* first so that redundant merges occur first */
5698     if ((size= qh_setsize (neighbor->neighbors)) < qh hull_dim) {
5699       qh_appendmergeset (neighbor, neighbor, &angledegen);
5700       trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate.  Neighbor of f%d.\n", neighbor->id, facet->id));
5701     }
5702   }
5703   qh vertex_visit++;
5704   FOREACHvertex_(facet->vertices)
5705     vertex->visitid= qh vertex_visit;
5706   FOREACHneighbor_(facet) {
5707     FOREACHvertex_(neighbor->vertices) {
5708       if ((int)vertex->visitid != qh vertex_visit)
5709         break;
5710     }
5711     if (!vertex) {
5712       qh_appendmergeset (neighbor, facet, &angleredundant);
5713       trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is contained in f%d.  merge\n", neighbor->id, facet->id));
5714     }
5715   }
5716 } /* degen_redundant_neighbors */
5717 
5718 
5719 /*-------------------------------------------------
5720 -facetdegen- true if facet already in mergeset as a degenerate
5721 */
qh_facetdegen(facetT * facet)5722 boolT qh_facetdegen (facetT *facet) {
5723   mergeT *merge, **mergep;
5724 
5725   FOREACHmerge_(qh facet_mergeset) {
5726     if (merge->facet1 == facet && merge->angle == qh_ANGLEdegen)
5727         return True;
5728   }
5729   return False;
5730 } /* facetdegen */
5731 
5732 
5733 /*-----------------------------------------
5734 -find_newvertex - locate new vertex for renaming old vertex
5735   each ridge includes oldvertex
5736   vertices consists of possible new vertices
5737 returns:
5738   newvertex or NULL
5739   vertices sorted by number of deleted ridges
5740 notes:
5741   new vertex is in one of the ridges
5742   renaming will not cause a duplicate ridge
5743   renaming will minimize the number of deleted ridges
5744   newvertex may not be adjacent in the dual (though unlikely)
5745 */
qh_find_newvertex(vertexT * oldvertex,setT * vertices,setT * ridges)5746 vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges) {
5747   vertexT *vertex, **vertexp;
5748   setT *newridges;
5749   ridgeT *ridge, **ridgep, *dupridge;
5750   int size, hashsize;
5751   int hash;
5752 
5753   if (qh IStracing >= 4) {
5754     fprintf (qh ferr, "qh_find_newvertex: find new vertex for v%d from ",
5755 	     oldvertex->id);
5756     FOREACHvertex_(vertices)
5757       fprintf (qh ferr, "v%d ", vertex->id);
5758     FOREACHridge_(ridges)
5759       fprintf (qh ferr, "r%d ", ridge->id);
5760     fprintf (qh ferr, "\n");
5761   }
5762   FOREACHvertex_(vertices)
5763     vertex->visitid= 0;
5764   FOREACHridge_(ridges) {
5765     FOREACHvertex_(ridge->vertices)
5766       vertex->visitid++;
5767   }
5768   FOREACHvertex_(vertices) {
5769     if (!vertex->visitid) {
5770       qh_setdelnth (vertices, SETindex_(vertices,vertex));
5771       vertexp--; /* repeat since deleted this vertex */
5772     }
5773   }
5774   qh vertex_visit += qh_setsize (ridges);
5775   if (!qh_setsize (vertices)) {
5776     trace4((qh ferr, "qh_find_newvertex: vertices not in ridges for v%d\n",
5777 	    oldvertex->id));
5778     return NULL;
5779   }
5780   qsort (SETaddr_(vertices, vertexT), qh_setsize (vertices),
5781 	        sizeof (vertexT *), qh_comparevisit);
5782   /* can now use qh vertex_visit */
5783   if (qh PRINTstatistics) {
5784     size= qh_setsize (vertices);
5785     zinc_(Zintersect);
5786     zadd_(Zintersecttot, size);
5787     zmax_(Zintersectmax, size);
5788   }
5789   hashsize= qh_newhashtable (qh_setsize (ridges));
5790   FOREACHridge_(ridges)
5791     qh_hashridge (qh hash_table, hashsize, ridge, oldvertex);
5792   FOREACHvertex_(vertices) {
5793     newridges= qh_vertexridges (vertex);
5794     FOREACHridge_(newridges) {
5795       if ((dupridge= qh_hashridge_find (qh hash_table, hashsize, ridge, vertex, oldvertex, &hash))) {
5796 	zinc_(Zdupridge);
5797 	break;
5798       }
5799     }
5800     qh_settempfree (&newridges);
5801     if (!ridge)
5802       break;  /* found a rename */
5803   }
5804   if (vertex) {
5805     zinc_(Zfindvertex);
5806     trace2((qh ferr, "qh_find_newvertex: found v%d for old v%d from %d vertices and %d ridges.\n",
5807       vertex->id, oldvertex->id, qh_setsize (vertices), qh_setsize (ridges)));
5808   }else {
5809     zinc_(Zfindfail);
5810     trace0((qh ferr, "qh_find_newvertex: no vertex for renaming v%d (all duplicated ridges)\n",
5811       oldvertex->id));
5812   }
5813   qh_setfree (&qh hash_table);
5814   return vertex;
5815 } /* find_newvertex */
5816 
5817 /*-------------------------------------------------
5818 -findbest_test- test neighbor for findbestneighbor()
5819   either test centrum or vertices
5820 */
qh_findbest_test(boolT testcentrum,facetT * facet,facetT * neighbor,facetT ** bestfacet,realT * distp,realT * mindistp,realT * maxdistp)5821 void qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor,
5822       facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp) {
5823   realT dist, mindist, maxdist;
5824 
5825   if (testcentrum) {
5826     zzinc_(Zbestdist);
5827     qh_distplane(facet->center, neighbor, &dist);
5828     dist *= qh hull_dim; /* estimate furthest vertex */
5829     if (dist < 0) {
5830       maxdist= 0;
5831       mindist= dist;
5832       dist= -dist;
5833     }else
5834       maxdist= dist;
5835   }else
5836     dist= qh_getdistance (facet, neighbor, &mindist, &maxdist);
5837   if (dist < *distp) {
5838     *bestfacet= neighbor;
5839     *mindistp= mindist;
5840     *maxdistp= maxdist;
5841     *distp= dist;
5842   }
5843 } /* findbest_test */
5844 
5845 /*-------------------------------------------------
5846 -findbestneighbor- finds best neighbor (least dist) of a facet for merging
5847   returns min and max distances and their max absolute value
5848   avoids merging old into new
5849 */
qh_findbestneighbor(facetT * facet,realT * distp,realT * mindistp,realT * maxdistp)5850 facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp) {
5851   facetT *neighbor, **neighborp, *bestfacet= NULL;
5852   ridgeT *ridge, **ridgep;
5853   boolT nonconvex= True, testcentrum= False;
5854   int size= qh_setsize (facet->vertices);
5855 
5856   *distp= REALmax;
5857   if (size > qh hull_dim + qh_BESTcentrum) {
5858     testcentrum= True;
5859     zinc_(Zbestcentrum);
5860     if (!facet->center)
5861        facet->center= qh_getcentrum (facet);
5862   }
5863   if (size > qh hull_dim * qh_BESTnonconvex) {
5864     FOREACHridge_(facet->ridges) {
5865       if (ridge->nonconvex) {
5866         neighbor= otherfacet_(ridge, facet);
5867 	qh_findbest_test (testcentrum, facet, neighbor,
5868 			  &bestfacet, distp, mindistp, maxdistp);
5869       }
5870     }
5871   }
5872   if (!bestfacet) {
5873     nonconvex= False;
5874     FOREACHneighbor_(facet)
5875       qh_findbest_test (testcentrum, facet, neighbor,
5876 			&bestfacet, distp, mindistp, maxdistp);
5877   }
5878 
5879   if (!bestfacet) qhull_fatal(59);
5880 
5881   trace4((qh ferr, "qh_findbestneighbor: f%d is best neighbor for f%d testcentrum? %d nonconvex? %d dist %2.2g min %2.2g max %2.2g\n",
5882      bestfacet->id, facet->id, testcentrum, nonconvex, *distp, *mindistp, *maxdistp));
5883   return(bestfacet);
5884 } /* findbestneighbor */
5885 
5886 
5887 /*-------------------------------------------------
5888 -flippedmerges- merge flipped facets into best neighbor
5889   facet_mergeset may have degen/redundant from forced merges
5890   assumes facet_mergeset at top of temp stack
5891 returns:
5892   no flipped facets on facetlist
5893   degen/redundant merges passed through
5894 */
qh_flippedmerges(facetT * facetlist)5895 void qh_flippedmerges(facetT *facetlist) {
5896   facetT *facet, *neighbor, *facet1, *facet2;
5897   realT dist, mindist, maxdist;
5898   mergeT *merge;
5899   setT *othermerges= qh_settemp (qh TEMPsize);
5900   int nummerge=0;
5901 
5902   trace2((qh ferr, "qh_flippedmerges: begin\n"));
5903   FORALLfacet_(facetlist) {
5904     if (facet->flipped)
5905       qh_appendmergeset (facet, facet, NULL);
5906   }
5907   while ((merge= (mergeT *)qh_setdellast (qh facet_mergeset))) {
5908     if (merge->angle >= qh_ANGLEdegen) {  /* and qh_ANGLEredundant */
5909       qh_setappend (&othermerges, merge);
5910       continue;
5911     }
5912     facet1= merge->facet1;
5913     facet2= merge->facet2;
5914     qh_memfree (merge, sizeof(mergeT));
5915     if (facet1->visible || facet2->visible)
5916       continue;
5917     if (qh TRACEmerge-1 == zzval_(Ztotmerge))
5918       qhmem.IStracing= qh IStracing= qh TRACElevel;
5919     neighbor= qh_findbestneighbor (facet1, &dist, &mindist, &maxdist);
5920     trace0((qh ferr, "qh_flippedmerges: merge flipped f%d into f%d dist %2.2g\n",
5921       facet1->id, neighbor->id, dist));
5922     qh_mergefacet (facet1, neighbor, &mindist, &maxdist, NULL);
5923     nummerge++;
5924     if (qh PRINTstatistics) {
5925       zinc_(Zflipped);
5926       wadd_(Wflippedtot, dist);
5927       wmax_(Wflippedmax, dist);
5928     }
5929   }
5930   if (qh_setsize (othermerges)) {
5931     qh_settemppop();  /* othermerges, errors here will leave memory */
5932     qh_settempfree (&qh facet_mergeset);
5933     qh facet_mergeset= othermerges;
5934     qh_settemppush (othermerges);
5935   }else
5936     qh_settempfree (&othermerges);
5937   trace1((qh ferr, "qh_flippedmerges: merged %d flipped facets into a good neighbor\n", nummerge));
5938 } /* flippedmerges */
5939 
5940 
5941 /*-------------------------------------------------
5942 -forcedmerges- merge across duplicated ridges and mutually flipped facets
5943   duplicate ridges marked by MERGEridge and both sides facet->seen
5944   bumps visit_id
5945   assumes no merge has merge->newmerge
5946 returns:
5947   all neighboring, flipped facets merged together
5948   no duplicate ridges
5949   facet_mergeset includes any degen/redundant merges
5950   uses facet-tested
5951 notes:
5952   duplicate ridges occur when the horizon is pinched,
5953         i.e. a subridge occurs in more than two horizon ridges.
5954      could rename vertices that pinch the horizon
5955 */
qh_forcedmerges(facetT * facetlist)5956 void qh_forcedmerges(facetT *facetlist) {
5957   facetT *facet, *neighbor, **neighborp, *facet1, *facet2;
5958   mergeT *merge, **mergep;
5959   realT dist1, dist2, mindist1, mindist2, maxdist1, maxdist2;
5960   int nummerge=0, numflip=0;
5961 
5962   if (qh TRACEmerge-1 == zzval_(Ztotmerge))
5963     qhmem.IStracing= qh IStracing= qh TRACElevel;
5964   trace2((qh ferr, "qh_forcedmerges: begin\n"));
5965   qh visit_id++;
5966   FORALLfacet_(facetlist) {
5967     facet->tested= True;
5968     if (facet->seen || facet->flipped) {
5969       facet->visitid= qh visit_id;
5970       FOREACHneighbor_(facet) {
5971         if (neighbor == qh_MERGEridge) {
5972 	  facet->tested= False;
5973 	  continue;
5974 	}
5975         if (neighbor->seen && facet->seen
5976 	&& !qh_setin (neighbor->neighbors, facet)) {  /* qh_MERGEridge */
5977 	  merge= qh_appendmergeset (facet, neighbor, NULL);
5978 	  merge->mergeridge= True;
5979 	}
5980 	if ((int)neighbor->visitid == qh visit_id)
5981           continue;
5982 	if (neighbor->flipped && facet->flipped)
5983           qh_appendmergeset (facet, neighbor, NULL);
5984       }
5985     }
5986   }
5987   FORALLfacet_(facetlist) {            /* gets rid of qh_MERGEridge */
5988     if (!facet->tested)
5989       qh_makeridges (facet);
5990   }
5991   FOREACHmerge_(qh facet_mergeset) {   /* restore the missing neighbors */
5992     if (merge->mergeridge) {
5993       qh_setappend (&merge->facet2->neighbors, merge->facet1);
5994       qh_makeridges (merge->facet1);   /* and the missing ridges */
5995     }
5996   }
5997  LABELrestart_merges:
5998   FOREACHmerge_(qh facet_mergeset) {   /* do duplicates first */
5999     if (!merge->mergeridge)
6000       continue;
6001     facet1= merge->facet1;
6002     facet2= merge->facet2;
6003     while (facet1->visible)
6004       facet1= (facetT *)SETfirst_(facet1->neighbors);
6005     while (facet2->visible)
6006       facet2= (facetT *)SETfirst_(facet2->neighbors);
6007     if (facet1 == facet2)
6008       continue;
6009     if (!qh_setin (facet2->neighbors, facet1)) qhull_fatal(60);
6010 
6011     if (qh TRACEmerge-1 == zzval_(Ztotmerge))
6012       qhmem.IStracing= qh IStracing= qh TRACElevel;
6013     if (facet1->flipped || facet2->flipped) {
6014       zinc_(Zmergeflipdup);
6015       numflip++;
6016       trace0((qh ferr, "qh_forcedmerges: duplicate ridge with a flipped facet for f%d and f%d\n",
6017 	      facet1->id, facet2->id));
6018       if (facet1->flipped)     /* delay until qh_flippedmerges */
6019 	qh_mergefacet (facet2, facet1, NULL, NULL, NULL);
6020       else
6021 	qh_mergefacet (facet1, facet2, NULL, NULL, NULL);
6022       zinc_(Zmergeflip);
6023     }else {
6024       dist1= qh_getdistance (facet1, facet2, &mindist1, &maxdist1);
6025       dist2= qh_getdistance (facet2, facet1, &mindist2, &maxdist2);
6026       trace0((qh ferr, "qh_forcedmerges: duplicate ridge between f%d and f%d, dist %2.2g and reverse dist %2.2g\n",
6027 	      facet1->id, facet2->id, dist1, dist2));
6028       if (dist1 < dist2)
6029 	qh_mergefacet (facet1, facet2, &mindist1, &maxdist1, NULL);
6030       else {
6031 	dist1= dist2;
6032 	qh_mergefacet (facet2, facet1, &mindist2, &maxdist2, NULL);
6033       }
6034       nummerge++;
6035       if (qh PRINTstatistics) {
6036 	zinc_(Zduplicate);
6037 	wadd_(Wduplicatetot, dist1);
6038 	wmax_(Wduplicatemax, dist1);
6039       }
6040     }
6041     goto LABELrestart_merges;  /* facet_mergeset may have changed */
6042   }
6043   while ((merge= (mergeT *)qh_setdellast (qh facet_mergeset))) {
6044     if (merge->newmerge)
6045       break;
6046     facet1= merge->facet1;
6047     facet2= merge->facet2;
6048     if (merge->mergeridge || facet1->visible || facet2->visible)
6049       qh_memfree (merge, sizeof(mergeT));
6050     else if (facet1 == facet2 || !facet1->flipped || !facet2->flipped) {
6051       merge->newmerge= True;
6052       qh_setaddnth (&qh facet_mergeset, 0, merge);
6053     }else {
6054       if (qh TRACEmerge-1 == zzval_(Ztotmerge))
6055 	qhmem.IStracing= qh IStracing= qh TRACElevel;
6056       qh_memfree (merge, sizeof(mergeT));
6057       zinc_(Zmergeflip);
6058       trace3((qh ferr, "qh_forcedmerges: merge flipped facets f%d and f%d\n",
6059 	      facet1->id, facet2->id));
6060       qh_mergefacet (facet1, facet2, NULL, NULL, NULL);
6061       numflip++;
6062     }
6063   }
6064   trace1((qh ferr, "qh_forcedmerges: merged %d facets across duplicated ridges and %d flipped facets\n", nummerge, numflip));
6065 } /* forcedmerges */
6066 
6067 
6068 /*-------------------------------------------------
6069 -getdistance- returns the max and min distance of any vertex from neighbor
6070   returns the max absolute value
6071 */
qh_getdistance(facetT * facet,facetT * neighbor,realT * mindist,realT * maxdist)6072 realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist) {
6073   vertexT *vertex, **vertexp;
6074   realT dist;
6075 
6076   FOREACHvertex_(facet->vertices)
6077     vertex->seen= False;
6078   FOREACHvertex_(neighbor->vertices)
6079     vertex->seen= True;
6080   *mindist= 0.0;
6081   *maxdist= 0.0;
6082   FOREACHvertex_(facet->vertices) {
6083     if (!vertex->seen) {
6084       zzinc_(Zbestdist);
6085       qh_distplane(vertex->point, neighbor, &dist);
6086       if (dist > *maxdist)
6087         *maxdist= dist;
6088       else if (dist < *mindist)
6089         *mindist= dist;
6090     }
6091   }
6092   return fmax_(*maxdist, -(*mindist));
6093 } /* getdistance */
6094 
6095 
6096 /*-------------------------------------------------
6097 -getmergeset- returns facet_mergeset of facet-neighbor pairs to be merged
6098     only tests !tested ridges of !tested facets
6099 returns:
6100     sorted mergeset
6101     all ridges tested
6102 notes:
6103   uses ridge->tested to prevent duplicate tests
6104   resets ridge->tested if !facet->center
6105   can not limit tests to modified ridges since the centrum changed
6106 */
qh_getmergeset(facetT * facetlist)6107 void qh_getmergeset(facetT *facetlist) {
6108   facetT *facet, *neighbor, **neighborp;
6109   ridgeT *ridge, **ridgep;
6110   int nummerges;
6111 
6112   nummerges= qh_setsize (qh facet_mergeset);
6113   trace2((qh ferr, "qh_getmergeset: started.\n"));
6114   FORALLfacet_(facetlist) {
6115     if (!facet->center) {
6116       facet->tested= False;
6117       FOREACHridge_(facet->ridges)
6118 	ridge->tested= False;
6119     }
6120     if (facet->tested)
6121       continue;
6122     facet->tested= True;  /* must be non-simplicial */
6123     FOREACHneighbor_(facet)
6124       neighbor->seen= False;
6125     FOREACHridge_(facet->ridges) {
6126       if (ridge->tested && !ridge->nonconvex)
6127 	continue;
6128       ridge->tested= True;
6129       ridge->nonconvex= False;
6130       neighbor= otherfacet_(ridge, facet);
6131       if (!neighbor->seen) {
6132 	neighbor->seen= True;
6133 	if (qh_test_appendmerge (facet, neighbor))
6134 	  ridge->nonconvex= True;
6135       }
6136     }
6137   }
6138   nummerges= qh_setsize (qh facet_mergeset);
6139   qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_compareangle);
6140   trace2((qh ferr, "qh_getmergeset: %d merges found\n", nummerges));
6141 } /* getmergeset */
6142 
6143 
6144 /*------------------------------------------------
6145 -getmergeset_initial- initial mergeset for facets
6146   tests all facet/neighbor pairs on facetlist
6147   uses visit_id
6148   facet_mergeset may have degen/redundant from flipped and forced merges
6149 returns:
6150   sorted mergeset
6151   sets facet->tested and ridge->tested
6152 */
qh_getmergeset_initial(facetT * facetlist)6153 void qh_getmergeset_initial (facetT *facetlist) {
6154   facetT *facet, *neighbor, **neighborp;
6155   ridgeT *ridge, **ridgep;
6156   int nummerges;
6157 
6158   qh visit_id++;
6159   FORALLfacet_(facetlist) {
6160     facet->visitid= qh visit_id;
6161     facet->tested= True;
6162     FOREACHneighbor_(facet) {
6163       if ((int)neighbor->visitid != qh visit_id) {
6164         if (qh_test_appendmerge (facet, neighbor)) {
6165           if (!neighbor->simplicial) {
6166             FOREACHridge_(neighbor->ridges) {
6167               if (facet == otherfacet_(ridge, neighbor)) {
6168                 ridge->nonconvex= True;
6169                 break;
6170               }
6171             }
6172           }
6173         }
6174       }
6175     }
6176     FOREACHridge_(facet->ridges)
6177       ridge->tested= True;
6178   }
6179   nummerges= qh_setsize (qh facet_mergeset);
6180   qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_compareangle);
6181   trace2((qh ferr, "qh_getmergeset_initial: %d merges found\n", nummerges));
6182 } /* getmergeset_initial */
6183 
6184 
6185 /*-----------------------------------------
6186 -hashridge- add ridge to hashtable without oldvertex
6187   assumes hashtable is large enough
6188 */
qh_hashridge(setT * hashtable,int hashsize,ridgeT * ridge,vertexT * oldvertex)6189 void qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex) {
6190   unsigned hash;
6191   ridgeT *ridgeA;
6192 
6193   hash= qh_gethash (hashsize, ridge->vertices, qh hull_dim-1, 0, oldvertex);
6194   while (True) {
6195     if (!(ridgeA= (ridgeT *)SETelem_(hashtable, hash))) {
6196       SETelem_(hashtable, hash)= ridge;
6197       break;
6198     }else if (ridgeA == ridge)
6199       break;
6200     if ((int)(++hash) == hashsize)
6201       hash= 0;
6202   }
6203 } /* hashridge */
6204 
6205 
6206 /*-----------------------------------------
6207 -hashridge_find- returns matching ridge in hashtable without oldvertex
6208   assumes hashtable is large enough
6209   can't match ridge to itself
6210   if oldvertex is NULL matches with one skip
6211 returns:
6212   returns matching ridge;
6213   if no match,
6214     hashslot= -1 if ridge already in table
6215       else next NULL index
6216 */
qh_hashridge_find(setT * hashtable,int hashsize,ridgeT * ridge,vertexT * vertex,vertexT * oldvertex,int * hashslot)6217 ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge,
6218               vertexT *vertex, vertexT *oldvertex, int *hashslot) {
6219   unsigned hash;
6220   ridgeT *ridgeA;
6221 
6222   *hashslot= 0;
6223   zinc_(Zhashridge);
6224   hash= qh_gethash (hashsize, ridge->vertices, qh hull_dim-1, 0, vertex);
6225   while ((ridgeA= (ridgeT *)SETelem_(hashtable, hash))) {
6226     if (ridgeA == ridge)
6227       *hashslot= -1;
6228     else {
6229       zinc_(Zhashridgetest);
6230       if (qh_setequal_except (ridge->vertices, vertex, ridgeA->vertices, oldvertex))
6231         return ridgeA;
6232     }
6233     if ((int)(++hash) == hashsize)
6234       hash= 0;
6235   }
6236   if (!*hashslot)
6237     *hashslot= hash;
6238   return NULL;
6239 } /* hashridge_find */
6240 
6241 
6242 /*-------------------------------------------------
6243 -makeridges- creates explicit ridges between simplicial facets
6244   allows qh_MERGEridge flag
6245   uses existing ridges
6246 returns:
6247   facet with ridges and without qh_MERGEridge
6248 */
qh_makeridges(facetT * facet)6249 void qh_makeridges(facetT *facet) {
6250   facetT *neighbor, **neighborp;
6251   ridgeT *ridge, **ridgep;
6252   int neighbor_i, neighbor_n;
6253   boolT toporient=False, mergeridge= False;
6254 
6255   if (!facet->simplicial)
6256     return;
6257   trace4((qh ferr, "qh_makeridges: make ridges for f%d\n", facet->id));
6258   facet->simplicial= False;
6259   FOREACHneighbor_(facet) {
6260     if (neighbor == qh_MERGEridge)
6261       mergeridge= True;
6262     else
6263       neighbor->seen= False;
6264   }
6265   FOREACHridge_(facet->ridges)
6266     otherfacet_(ridge, facet)->seen= True;
6267   FOREACHneighbor_i_(facet) {
6268     if (neighbor == qh_MERGEridge) {
6269       FOREACHridge_(facet->ridges) {
6270 	if (!qh_setin (facet->neighbors, otherfacet_(ridge, facet)))
6271 	  ridge->mergeridge= True;
6272       }
6273     }else if (!neighbor->seen) {
6274       ridge= qh_newridge();
6275       if (!neighbor->simplicial)   /* only in forced merges, checkfacet */
6276 	ridge->mergeridge= True;
6277       ridge->vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim,
6278 					                  neighbor_i, 0);
6279       toporient= (boolT)( facet->toporient ^ (neighbor_i & 0x1) );
6280       if (toporient) {
6281         ridge->top= facet;
6282         ridge->bottom= neighbor;
6283       }else {
6284         ridge->top= neighbor;
6285         ridge->bottom= facet;
6286       }
6287 #if 0 /* this also works */
6288       flip= (facet->toporient ^ neighbor->toporient)^(skip1 & 0x1) ^ (skip2 & 0x1);
6289       if (facet->toporient ^ (skip1 & 0x1) ^ flip) {
6290         ridge->top= neighbor;
6291         ridge->bottom= facet;
6292       }else {
6293         ridge->top= facet;
6294         ridge->bottom= neighbor;
6295       }
6296 #endif
6297       qh_setappend(&(facet->ridges), ridge);
6298       qh_setappend(&(neighbor->ridges), ridge);
6299     }
6300   }
6301   if (mergeridge) {
6302     while (qh_setdel (facet->neighbors, qh_MERGEridge))
6303       ; /* delete each one */
6304   }
6305 } /* makeridges */
6306 
6307 
6308 /*-------------------------------------------
6309 -maydropneighbor -- drop neighbor relationship if no ridge between facet and neighbor
6310   bumps qh visit_id
6311 returns:
6312   appends degenerate facets to facet_mergeset
6313   won't cause redundant facets since vertex inclusion is the same
6314   may drop vertex and neighbor if no ridge
6315 */
qh_maydropneighbor(facetT * facet)6316 void qh_maydropneighbor (facetT *facet) {
6317   ridgeT *ridge, **ridgep;
6318   realT angledegen= qh_ANGLEdegen;
6319   facetT *neighbor, **neighborp;
6320 
6321   qh visit_id++;
6322   trace4((qh ferr, "qh_maydropneighbor: test f%d for no ridges to a neighbor\n",
6323 	  facet->id));
6324   FOREACHridge_(facet->ridges) {
6325     ridge->top->visitid= qh visit_id;
6326     ridge->bottom->visitid= qh visit_id;
6327   }
6328   FOREACHneighbor_(facet) {
6329     if ((int)neighbor->visitid != qh visit_id) {
6330       trace0((qh ferr, "qh_maydropneighbor: facets f%d and f%d are no longer neighbors\n",
6331 	    facet->id, neighbor->id));
6332       zinc_(Zdropneighbor);
6333       qh_setdel (facet->neighbors, neighbor);
6334       neighborp--;  /* repeat, deleted a neighbor */
6335       qh_setdel (neighbor->neighbors, facet);
6336       if (qh_setsize (neighbor->neighbors) < qh hull_dim) {
6337         zinc_(Zdropdegen);
6338         qh_appendmergeset (neighbor, neighbor, &angledegen);
6339         trace2((qh ferr, "qh_maydropneighbors: f%d is degenerate.\n", neighbor->id));
6340       }
6341     }
6342   }
6343   if (qh_setsize (facet->neighbors) < qh hull_dim) {
6344     zinc_(Zdropdegen);
6345     qh_appendmergeset (facet, facet, &angledegen);
6346     trace2((qh ferr, "qh_maydropneighbors: f%d is degenerate.\n", facet->id));
6347   }
6348 } /* maydropneighbor */
6349 
6350 
6351 /*---------------------------------------
6352 -merge_degenredundant- merge degenerate and redundant facets
6353   if facet1 undefined, tests last merge on facet_mergeset and sets angle
6354 returns:
6355   True if merge performed or degen merge not needed
6356 notes:
6357   need this since renaming vertices can result in degen/redundant facets
6358   any merge can also result in degen/redundant facets
6359 */
qh_merge_degenredundant(facetT * facet1,facetT * facet2,realT * angle)6360 boolT qh_merge_degenredundant (facetT *facet1, facetT *facet2, realT *angle) {
6361   int numnewmerges= 0, size;
6362   mergeT *merge;
6363   facetT *bestneighbor;
6364   realT dist, mindist, maxdist;
6365   vertexT *vertex, **vertexp;
6366 
6367   if (qh TRACEmerge-1 == zzval_(Ztotmerge))
6368     qhmem.IStracing= qh IStracing= qh TRACElevel;
6369   while (!facet1 && (merge= (mergeT *)qh_setlast (qh facet_mergeset))
6370 	 && merge->angle >= qh_ANGLEdegen) {
6371     merge= (mergeT *)qh_setdellast (qh facet_mergeset);
6372     facet1= merge->facet1;
6373     facet2= merge->facet2;
6374     *angle= merge->angle;
6375     qh_memfree (merge, sizeof(mergeT));
6376     if (facet1->visible || facet2->visible)
6377       facet1= NULL;
6378   }
6379   if (!facet1)
6380     return False;
6381   if (*angle == qh_ANGLEredundant) {
6382     trace2((qh ferr, "qh_merge_degenredundant: facet f%d is contained in f%d, will merge\n",
6383 	    facet1->id, facet2->id));
6384     qh_mergefacet(facet1, facet2, NULL, NULL, angle);
6385     qh_newmerge_(facet2);
6386     zinc_(Zneighbor);
6387   }else if (*angle == qh_ANGLEdegen) {   /* other merges may have fixed */
6388     if (!(size= qh_setsize (facet1->neighbors))) {
6389       trace2((qh ferr, "qh_merge_degenredundant: facet f%d has no neighbors.  Deleted\n", facet1->id));
6390       zinc_(Zdelfacetdup);
6391       qh_removefacet(facet1);
6392       qh_prependfacet (facet1, &qh visible_list);
6393       qh num_visible++;
6394       facet1->visible= True;
6395       /* SETfirst_(facet1->neighbors) == NULL */
6396       FOREACHvertex_(facet1->vertices) {
6397 	qh_setdel (vertex->neighbors, facet1);
6398 	if (!SETfirst_(vertex->neighbors)) {
6399 	  zinc_(Zdegenvertex);
6400 	  trace2((qh ferr, "qh_merge_degenredundant: deleted v%d because f%d has no neighbors\n",
6401           vertex->id, facet1->id));
6402 	  vertex->deleted= True;
6403 	  qh_setappend (&qh del_vertices, vertex);
6404 	}
6405       }
6406       numnewmerges++;  /* needed since cleared this merge */
6407     }else if (size < qh hull_dim) {
6408       bestneighbor= qh_findbestneighbor(facet1, &dist, &mindist, &maxdist);
6409       trace2((qh ferr, "qh_merge_degenredundant: facet f%d has %d neighbors, merge into f%d dist %2.2g\n",
6410 	      facet1->id, size, bestneighbor->id, dist));
6411       qh_mergefacet(facet1, bestneighbor, &mindist, &maxdist, angle);
6412       qh_newmerge_(bestneighbor);
6413       if (qh PRINTstatistics) {
6414 	zinc_(Zdegen);
6415 	wadd_(Wdegentot, dist);
6416 	wmax_(Wdegenmax, dist);
6417       }
6418     }else
6419       numnewmerges++;  /* needed since cleared this merge */
6420   }
6421   return (boolT)numnewmerges;
6422 } /* merge_degenredundant */
6423 
6424 /*-------------------------------------------------
6425 -merge_nonconvex- merges all nonconvex facets
6426   assumes qh_vertexneighbors() already called
6427   need to use qh newfacet_list since merge calls removefacet()
6428 returns:
6429   deleted facets added to visible_list
6430 notes:
6431   numdegenredun also counts degen facets that become ok
6432 */
qh_merge_nonconvex(void)6433 void qh_merge_nonconvex (void /*qh newfacet_list*/) {
6434   facetT *bestfacet, *neighbor, *facet1, *facet2;
6435   facetT *bestneighbor;
6436   mergeT *merge;
6437   realT dist, dist2, mindist, mindist2, maxdist, maxdist2, angle;
6438   boolT wasmerge= True, ismodified=False, anglecoplanar = False;
6439   void **freelistp;
6440   vertexT *vertex;
6441   int nummerge=0, numconcave=0, numdegenredun= 0, numnewmerges= 0;
6442 
6443   trace2((qh ferr, "qh_merge_nonconvex: starting to merge facets beginning from f%d\n",
6444 	    getid_(qh newfacet_list)));
6445   if (qh IStracing >= 4 && qh num_facets < 50)
6446     qh_printlists();
6447   qh facet_mergeset= qh_settemp (qh TEMPsize);
6448   qh_forcedmerges (qh newfacet_list);    /* also sets tested */
6449   qh_flippedmerges (qh newfacet_list);
6450   qh NEWmerges= True;
6451   if (qh POSTmerging)
6452     qh_tracemerging ("after flipped merges");
6453   qh_getmergeset_initial (qh newfacet_list); /* facet_mergeset */
6454   while (wasmerge) {
6455     wasmerge= False;
6456     while (qh_setsize (qh facet_mergeset)) {
6457       while ((merge= (mergeT *)qh_setdellast(qh facet_mergeset))) {
6458 	facet1= merge->facet1;
6459 	facet2= merge->facet2;
6460 	angle= merge->angle;
6461 	anglecoplanar= (boolT)merge->anglecoplanar;
6462 	qh_memfree_(merge, sizeof(mergeT), freelistp);
6463 	if ((facet1->id >= qh newfacet_id && !facet1->tested)
6464 	    || (facet2->id >= qh newfacet_id && !facet2->tested))
6465 	  ismodified= True;
6466 	else
6467 	  ismodified= False;
6468 	if (facet1->visible || facet2->visible) /*deleted facet*/
6469 	  continue;
6470 	if (ismodified && angle < qh_ANGLEconcave)
6471 	  continue;
6472 	if (qh TRACEmerge-1 == zzval_(Ztotmerge))
6473 	  qhmem.IStracing= qh IStracing= qh TRACElevel;
6474 	trace4((qh ferr, "qh_merge_nonconvex: merge #%d for f%d and f%d angle %2.2g modified? %d\n",
6475 	    zzval_(Ztotmerge)+1, facet1->id, facet2->id, angle, ismodified));
6476 	if (qh_merge_degenredundant (facet1, facet2, &angle)) {
6477 	  numdegenredun++;
6478 	  wasmerge= True;
6479 	  continue;
6480 	}else {  /* ANGLEconcave or coplanar */
6481 	  if (facet1->id < qh newfacet_id) {
6482 	    bestfacet= facet2;   /* avoid merging old facet if new is ok */
6483 	    facet2= facet1;
6484 	    facet1= bestfacet;
6485 	  }else
6486  	    bestfacet= facet1;
6487 	  bestneighbor= qh_findbestneighbor(bestfacet, &dist, &mindist, &maxdist);
6488 	  neighbor= qh_findbestneighbor(facet2, &dist2, &mindist2, &maxdist2);
6489 	  wasmerge= True;
6490 	  if (dist < dist2) {
6491 	    qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, &angle);
6492 	    qh_newmerge_(bestneighbor);
6493 	  }else if (facet2->id < qh newfacet_id
6494 	  && ((mindist >= qh min_vertex && maxdist <= qh max_outside)
6495 	       || dist * 1.5 < dist2)) {
6496 	    zinc_(Zavoidold);
6497 	    wadd_(Wavoidoldtot, dist);
6498 	    wmax_(Wavoidoldmax, dist);
6499 	    trace2((qh ferr, "qh_merge_nonconvex: avoid merging old facet f%d dist %2.2g.  Use f%d dist %2.2g insted\n",
6500 		    facet2->id, dist2, facet1->id, dist2));
6501 	    qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, &angle);
6502 	    qh_newmerge_(bestneighbor);
6503 	  }else {
6504 	    qh_mergefacet(facet2, neighbor, &mindist2, &maxdist2, &angle);
6505 	    qh_newmerge_(neighbor);
6506 	    dist= dist2;
6507 	  }
6508 	  if (qh PRINTstatistics) {
6509 	    if (anglecoplanar) {
6510 	      nummerge++;
6511 	      zinc_(Zacoplanar);
6512 	      wadd_(Wacoplanartot, dist);
6513 	      wmax_(Wacoplanarmax, dist);
6514 	    }else if (angle > qh_ANGLEconcave) {
6515 	      numconcave++;
6516 	      zinc_(Zconcave);
6517 	      wadd_(Wconcavetot, dist);
6518 	      wmax_(Wconcavemax, dist);
6519 	    }else {
6520 	      nummerge++;
6521 	      zinc_(Zcoplanar);
6522 	      wadd_(Wcoplanartot, dist);
6523 	      wmax_(Wcoplanarmax, dist);
6524 	    }
6525 	  }else if (angle > qh_ANGLEconcave)
6526 	    numconcave++;
6527 	  else
6528 	    nummerge++;
6529 	}
6530 	/* reducing vertices here in 5-d, 50% more time, maybe fewer vertices,
6531 	               and better bounds */
6532       } /* while setdellast */
6533       if (qh POSTmerging)
6534 	qh_tracemerging ("after a merge set");
6535       if (numnewmerges > qh_MAXnewmerges) {  /* needed for large post merges */
6536 	numnewmerges= 0;
6537 	qh_reducevertices_centrums();
6538       }
6539       qh_getmergeset (qh newfacet_list); /* facet_mergeset */
6540     } /* while mergeset */
6541     if (wasmerge || (qh hull_dim >=4 && qh POSTmerging)) {
6542       if (qh hull_dim >=4 && qh POSTmerging) { /*duplicate ridges may changed*/
6543 	FORALLvertices
6544 	  vertex->delridge= True;
6545       }
6546       if (qh_reducevertices_centrums())
6547 	qh_getmergeset (qh newfacet_list); /* facet_mergeset */
6548       else
6549 	wasmerge= False;
6550     }
6551   } /* while (wasmerge) */
6552   qh NEWmerges= False;
6553   if (qh CHECKfrequently)
6554     qh_checkconvex (qh newfacet_list, qh_ALGORITHMfault);
6555   qh_settempfree(&qh facet_mergeset);
6556   trace1((qh ferr, "qh_merge_nonconvex: merged %d coplanar facets %d concave facets and %d degen or redundant facets.\n",
6557     nummerge, numconcave, numdegenredun));
6558   if (qh IStracing >= 4 && qh num_facets < 50)
6559     qh_printlists ();
6560 } /* merge_nonconvex */
6561 
6562 
6563 /*-------------------------------------------------
6564 -mergefacet- merges facet1 into facet2
6565   traces merge if fmax_(maxdist,-mindist) > TRACEdist
6566   mindist/maxdist and angle may be NULL
6567   max_outside and min_vertex updated
6568 returns:
6569   facet1 prepended to visible_list for later deletion and partitioning
6570      qh num_visible updated.
6571      SETfirst_(facet1->neighbors) == facet2
6572   facet2 moved to end of qh facet_list
6573     facet2 is new (get's facet1->id if it was old)
6574   adds neighboring facets to facet_mergeset if redundant or degenerate
6575   clears facet->tested and ridge->tested ffrom facet1
6576 */
qh_mergefacet(facetT * facet1,facetT * facet2,realT * mindist,realT * maxdist,realT * angle)6577 void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, realT *angle) {
6578   boolT traceonce= False, waserror= False;
6579   vertexT *vertex, **vertexp;
6580   ridgeT *ridge, **ridgep;
6581   int tracerestore=0;
6582 
6583   zzinc_(Ztotmerge);
6584   if ((mindist && (-*mindist > qh TRACEdist || *maxdist > qh TRACEdist))
6585   || facet1 == qh tracefacet || facet2 == qh tracefacet) {
6586     if (facet1 == qh tracefacet || facet2 == qh tracefacet) {
6587       tracerestore= qh IStracing;
6588       qh IStracing= 4;
6589       fprintf (qh ferr, "qh_mergefacet: ========= trace merge %d involving f%d, furthest is p%d\n",
6590 	       zzval_(Ztotmerge), qh tracefacet_id,  qh furthest_id);
6591     }else {
6592       tracerestore= 0;
6593       qh IStracing= qh TRACElevel;
6594       fprintf (qh ferr, "qh_mergefacet: ========= trace wide merge %d (%2.2g) for f%d into f%d, last point was p%d\n", zzval_(Ztotmerge),
6595            fmax_(-*mindist, *maxdist), facet1->id, facet2->id, qh furthest_id);
6596     }
6597     traceonce= True;
6598   }
6599   if (qh IStracing >= 2) {
6600     realT mergemin= -2;
6601     realT mergemax= -2;
6602     realT mergeangle= -2;
6603 
6604     if (mindist) {
6605       mergemin= *mindist;
6606       mergemax= *maxdist;
6607     }
6608     if (angle)
6609       mergeangle= *angle;
6610     fprintf (qh ferr, "qh_mergefacet: #%d merge f%d into f%d, mindist= %2.2g, maxdist= %2.2g, angle = %2.2g\n",
6611     zzval_(Ztotmerge), facet1->id, facet2->id, mergemin, mergemax, mergeangle);
6612   }
6613 
6614   if (facet1 == facet2 || facet1->visible || facet2->visible)
6615     qhull_fatal(61);
6616 
6617   if (qh num_facets -qh num_visible <= qh hull_dim + 1) qhull_fatal(62);
6618 
6619   if (mindist) {
6620     maximize_(qh max_outside, *maxdist);
6621     maximize_(qh max_vertex, *maxdist);
6622 #if qh_MAXoutside
6623     maximize_(facet2->maxoutside, *maxdist);
6624 #endif
6625     minimize_(qh min_vertex, *mindist);
6626   }
6627   qh_makeridges(facet1);
6628   qh_makeridges(facet2);
6629 
6630   /*
6631   if (qh IStracing >=4)
6632     qh_errprint ("MERGING", facet1, facet2, NULL, NULL);
6633     NO LONGER IN SERVICE */
6634 
6635   if (facet2->center && qh hull_dim == 2) {  /* only two vertices */
6636     qh_memfree (facet2->center, qh center_size);
6637     facet2->center= NULL;
6638   }
6639   qh_mergeneighbors(facet1, facet2);
6640   FOREACHridge_(facet1->ridges)
6641     ridge->tested= False;
6642   qh_mergeridges(facet1, facet2);
6643   qh vertex_visit++;
6644   FOREACHvertex_(facet2->vertices)
6645     vertex->visitid= qh vertex_visit;
6646   if (qh hull_dim == 2)
6647     qh_mergevertices2d(facet1->vertices, facet2->vertices);
6648   else
6649     qh_mergevertices(facet1->vertices, &facet2->vertices);
6650   qh_mergevertex_neighbors(facet1, facet2);
6651   if (facet1->id < qh newfacet_id && facet2->id >= qh newfacet_id) {
6652     zinc_(Zmergehorizon);
6653   }else if (facet2->id >= qh newfacet_id)
6654     zinc_(Zmergenew);
6655   qh_removefacet(facet1);
6656   qh_prependfacet (facet1, &qh visible_list);
6657   qh num_visible++;
6658   facet1->visible= True;
6659   SETfirst_(facet1->neighbors)= facet2;
6660   qh_settruncate (facet1->neighbors, 1);
6661   qh_removefacet(facet2);  /* append as a newfacet to end of qh facet_list */
6662   qh_appendfacet(facet2);
6663   if (facet2->id < qh newfacet_id) {
6664     zinc_(Zmergeintohorizon);
6665     trace3((qh ferr, "qh_mergefacet: RENAME - f%d as new facet f%d\n",
6666       facet2->id, qh facet_id));
6667     if (qh facet_id == (int)qh tracefacet_id) {
6668       qh tracefacet= facet2;
6669       fprintf (qh ferr, "qh_mergefacet: RENAME f%d as trace facet f%d.  Current furthest is p%d\n",
6670 	       facet2->id, qh facet_id, qh furthest_id);
6671     }
6672     facet2->id= qh facet_id++;
6673   }
6674   qh_degen_redundant_neighbors (facet2);
6675   facet2->tested= False;
6676 
6677   /*
6678   if (qh IStracing >= 4)
6679     qh_errprint ("MERGED", facet2, NULL, NULL, NULL);
6680     NO LONGER IN SERVICE */
6681 
6682   if (facet2 == qh tracefacet || (qh tracevertex && qh tracevertex->newlist)) {
6683     fprintf (qh ferr, "qh_mergefacets: trace facet and vertex after merge of f%d and f%d, furthest p%d\n", facet1->id, facet2->id, qh furthest_id);
6684 
6685     /*
6686     if (facet2 != qh tracefacet)
6687       qh_errprint ("TRACE", qh tracefacet,
6688         (qh tracevertex ? (facetT *)SETfirst_(qh tracevertex->neighbors):NULL),
6689         NULL, qh tracevertex);
6690 	NO LONGER IN SERVICE */
6691 
6692   }
6693   if (qh CHECKfrequently || qh IStracing >= 4) { /* can't check polygon here */
6694     qh_checkfacet (facet2, True, &waserror);
6695 
6696     if (waserror) qhull_fatal(63);
6697 
6698     qh_checkridge_boundary (facet2);
6699   }
6700   if (qh tracevertex) {
6701     if (qh tracevertex->deleted)
6702       fprintf (qh ferr, "qh_mergefacet: trace vertex deleted at furthest p%d\n",
6703 	    qh furthest_id);
6704     else
6705       qh_checkvertex (qh tracevertex);
6706   }
6707   if (qh tracefacet) {
6708     qh_checkfacet (qh tracefacet, True, &waserror);
6709 
6710     if (waserror) qhull_fatal(64);
6711 
6712   }
6713   if (traceonce) {
6714     fprintf (qh ferr, "qh_mergefacet: end of wide tracing\n");
6715     qh IStracing= tracerestore;
6716   }
6717 } /* mergefacet */
6718 
6719 
6720 /*-------------------------------------------------
6721 -mergeneighbors- merges the neighbors of facet1 into facet2
6722 */
qh_mergeneighbors(facetT * facet1,facetT * facet2)6723 void qh_mergeneighbors(facetT *facet1, facetT *facet2) {
6724   facetT *neighbor, **neighborp;
6725 
6726   trace4((qh ferr, "qh_mergeneighbors: merge neighbors of f%d and f%d\n",
6727 	  facet1->id, facet2->id));
6728   qh visit_id++;
6729   FOREACHneighbor_(facet2) {
6730     neighbor->visitid= qh visit_id;
6731   }
6732   FOREACHneighbor_(facet1) {
6733     if ((int)neighbor->visitid == qh visit_id) {
6734       if (neighbor->simplicial)    /* is degen, needs ridges */
6735 	qh_makeridges (neighbor);
6736       if (SETfirst_(neighbor->neighbors) != facet1) /*keep horizon->newfacet*/
6737 	 qh_setdel (neighbor->neighbors, facet1);
6738       else {
6739         qh_setdel(neighbor->neighbors, facet2);
6740         qh_setreplace(neighbor->neighbors, facet1, facet2);
6741       }
6742     }else if (neighbor != facet2) {
6743       qh_setappend(&(facet2->neighbors), neighbor);
6744       qh_setreplace(neighbor->neighbors, facet1, facet2);
6745     }
6746   }
6747   qh_setdel(facet1->neighbors, facet2);  /* here for makeridges */
6748   qh_setdel(facet2->neighbors, facet1);
6749 } /* mergeneighbors */
6750 
6751 
6752 /*-------------------------------------------------
6753 -mergeridges- merges the ridge set of facet1 into facet2
6754   may delete all ridges for a vertex
6755 */
qh_mergeridges(facetT * facet1,facetT * facet2)6756 void qh_mergeridges(facetT *facet1, facetT *facet2) {
6757   ridgeT *ridge, **ridgep;
6758   vertexT *vertex, **vertexp;
6759 
6760   trace4((qh ferr, "qh_mergeridges: merge ridges of f%d and f%d\n",
6761 	  facet1->id, facet2->id));
6762   FOREACHridge_(facet2->ridges) {
6763     if ((ridge->top == facet1) || (ridge->bottom == facet1)) {
6764       FOREACHvertex_(ridge->vertices)
6765         vertex->delridge= True;
6766       qh_delridge(ridge);
6767       ridgep--; /*repeat*/
6768     }
6769   }
6770   FOREACHridge_(facet1->ridges) {
6771     if (ridge->top == facet1)
6772       ridge->top= facet2;
6773     else
6774       ridge->bottom= facet2;
6775     qh_setappend(&(facet2->ridges), ridge);
6776   }
6777 } /* mergeridges */
6778 
6779 
6780 /*-------------------------------------------------
6781 -mergevertex_neighbors- merge the vertex neighbors of facet1 to facet2
6782   deletes vertices if only one neighbor
6783   assumes neighbor sets are good
6784 */
qh_mergevertex_neighbors(facetT * facet1,facetT * facet2)6785 void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2) {
6786   vertexT *vertex, **vertexp;
6787 
6788   trace4((qh ferr, "qh_mergevertex_neighbors: merge vertex neighbors of f%d and f%d\n",
6789 	  facet1->id, facet2->id));
6790   if (qh tracevertex) {
6791     fprintf (qh ferr, "qh_mergevertex_neighbors: of f%d and f%d at furthest p%d f0= %p\n",
6792 	     facet1->id, facet2->id, qh furthest_id, qh tracevertex->neighbors->e[0]);
6793 
6794     /*
6795     qh_errprint ("TRACE", NULL, NULL, NULL, qh tracevertex);
6796     NO LONGER IN SERVICE */
6797 
6798   }
6799   FOREACHvertex_(facet1->vertices) {
6800     if ((int)vertex->visitid != qh vertex_visit) {
6801       qh_setreplace(vertex->neighbors, facet1, facet2);
6802     }else {
6803       qh_setdel(vertex->neighbors, facet1);
6804       if (!SETsecond_(vertex->neighbors)) {
6805         zinc_(Zmergevertex);
6806         trace2((qh ferr, "qh_mergevertex_neighbors: deleted v%d when merging f%d into f%d\n",
6807           vertex->id, facet1->id, facet2->id));
6808         qh_setdelsorted (facet2->vertices, vertex);
6809         vertex->deleted= True;
6810         qh_setappend (&qh del_vertices, vertex);
6811       }
6812     }
6813   }
6814 
6815   /*
6816   if (qh tracevertex)
6817     qh_errprint ("TRACE", NULL, NULL, NULL, qh tracevertex);
6818     NO LONGER IN SERVICE */
6819 
6820 } /* mergevertex_neighbors */
6821 
6822 
6823 /*-------------------------------------------------
6824 -mergevertices- merges the vertex set of facet1 into facet2
6825   preserves vertex_visit for qh_mergevertex_neighbors
6826   updates qh newvertex_list
6827 */
qh_mergevertices(setT * vertices1,setT ** vertices2)6828 void qh_mergevertices(setT *vertices1, setT **vertices2) {
6829   int newsize= qh_setsize(vertices1)+qh_setsize(*vertices2) - qh hull_dim + 1;
6830   setT *mergedvertices;
6831   vertexT *vertex, **vertexp, **vertex2= SETaddr_(*vertices2, vertexT);
6832 
6833   mergedvertices= qh_settemp (newsize);
6834   FOREACHvertex_(vertices1) {
6835     if (!*vertex2 || vertex->id > (*vertex2)->id)
6836       qh_setappend (&mergedvertices, vertex);
6837     else {
6838       while (*vertex2 && (*vertex2)->id > vertex->id)
6839 	qh_setappend (&mergedvertices, *vertex2++);
6840       if (!*vertex2 || (*vertex2)->id < vertex->id)
6841 	qh_setappend (&mergedvertices, vertex);
6842       else
6843 	qh_setappend (&mergedvertices, *vertex2++);
6844     }
6845   }
6846   while (*vertex2)
6847     qh_setappend (&mergedvertices, *vertex2++);
6848   FOREACHvertex_(mergedvertices) {
6849     if (!vertex->newlist) {
6850       vertex->newlist= True;
6851       qh_removevertex (vertex);
6852       qh_appendvertex (vertex);
6853     }
6854   }
6855 
6856   if (newsize < qh_setsize (mergedvertices)) qhull_fatal(65);
6857 
6858   qh_setfree(vertices2);
6859   *vertices2= mergedvertices;
6860   qh_settemppop ();
6861 } /* mergevertices */
6862 
6863 
6864 /*-------------------------------------------------
6865 -mergevertices2d- merges vertices1 into vertices2 in 2-d case
6866   preserves vertex_visit for qh_mergevertex_neighbors
6867 */
qh_mergevertices2d(setT * vertices1,setT * vertices2)6868 void qh_mergevertices2d(setT *vertices1, setT *vertices2) {
6869   vertexT *vertex1A, *vertex1B, *vertex2A, *vertex2B, *vertexA, *vertexB;
6870 
6871   vertex1A= (vertexT *)SETfirst_(vertices1);
6872   vertex1B= (vertexT *)SETsecond_(vertices1);
6873   vertex2A= (vertexT *)SETfirst_(vertices2);
6874   vertex2B= (vertexT *)SETsecond_(vertices2);
6875   if (vertex1A == vertex2A) {
6876     vertexA= vertex1B;
6877     vertexB= vertex2B;
6878   }else if (vertex1A == vertex2B) {
6879     vertexA= vertex1B;
6880     vertexB= vertex2A;
6881   }else if (vertex1B == vertex2A) {
6882     vertexA= vertex1A;
6883     vertexB= vertex2B;
6884   }else { /* 1B == 2B */
6885     vertexA= vertex1A;
6886     vertexB= vertex2A;
6887   }
6888   if (vertexA->id > vertexB->id) {
6889     SETfirst_(vertices2)= vertexA;
6890     SETsecond_(vertices2)= vertexB;
6891   }else {
6892     SETfirst_(vertices2)= vertexB;
6893     SETsecond_(vertices2)= vertexA;
6894   }
6895 } /* mergevertices2d */
6896 
6897 /*-------------------------------------------------
6898 -neighbor_intersections- return intersection for vertex->neighbors
6899   returns temporary set of vertices
6900   does not include vertex
6901   NULL if an neighbor is simplicial
6902   NULL if empty set
6903 */
qh_neighbor_intersections(vertexT * vertex)6904 setT *qh_neighbor_intersections (vertexT *vertex) {
6905   facetT *neighbor, **neighborp, *neighborA, *neighborB;
6906   setT *intersect;
6907   int neighbor_i, neighbor_n;
6908 
6909   FOREACHneighbor_(vertex) {
6910     if (neighbor->simplicial)
6911       return NULL;
6912   }
6913   neighborA= (facetT *)SETfirst_(vertex->neighbors);
6914   neighborB= (facetT *)SETsecond_(vertex->neighbors);
6915   zinc_(Zintersectnum);
6916   if (!neighborA)
6917     return NULL;
6918   if (!neighborB)
6919     intersect= qh_setcopy (neighborA->vertices, 0);
6920   else
6921     intersect= qh_vertexintersect_new (neighborA->vertices, neighborB->vertices);
6922   qh_settemppush (intersect);
6923   qh_setdelsorted (intersect, vertex);
6924   FOREACHneighbor_i_(vertex) {
6925     if (neighbor_i >= 2) {
6926       zinc_(Zintersectnum);
6927       qh_vertexintersect (&intersect, neighbor->vertices);
6928       if (!SETfirst_(intersect)) {
6929         zinc_(Zintersectfail);
6930         qh_settempfree (&intersect);
6931         return NULL;
6932       }
6933     }
6934   }
6935   trace3((qh ferr, "qh_neighbor_intersections: %d vertices in neighbor intersection of v%d\n",
6936           qh_setsize (intersect), vertex->id));
6937   return intersect;
6938 } /* neighbor_intersections */
6939 
6940 /*-------------------------------------------------
6941 -reducevertices_centrums reduce vertex sets and reset centrums
6942   qh_isnewmerge_(facet) [i.e., flipped] true if merged since last call
6943   if 2-d, just clears newmerge flags
6944 returns:
6945   True if degen_redundant facets or redefined centrums
6946   vertices are renamed if possible
6947   centrum's reset for small (qh_MAXnewcentrum), newly merged or renamed facets
6948 */
qh_reducevertices_centrums(void)6949 boolT qh_reducevertices_centrums (void) {
6950   int numshare=0, numrename= 0, numcentrums= 0;
6951   int numdegenredun= 0;
6952   facetT *newfacet;
6953   vertexT *vertex, **vertexp;
6954   realT angle;
6955   ridgeT *ridge, **ridgep;
6956 
6957   if (qh hull_dim == 2) {
6958     FORALLnew_facets
6959       qh_clearnewmerge_(newfacet);
6960     return False;
6961   }
6962  LABELrestart:
6963   while (qh_merge_degenredundant (NULL, NULL, &angle))
6964     numdegenredun++;
6965   FORALLnew_facets {
6966     if (qh_isnewmerge_(newfacet)) /* this is seldom needed */
6967       qh_remove_extravertices (newfacet);
6968   }
6969   FORALLnew_facets {
6970     if (qh_isnewmerge_(newfacet)) {
6971       FOREACHvertex_(newfacet->vertices) {
6972 	if (vertex->delridge) {
6973 	  if (qh_rename_sharedvertex (vertex, newfacet)) {
6974 	    numshare++;
6975 	    vertexp--; /* repeat since deleted vertex */
6976 	  }
6977         }
6978       }
6979     }
6980   }
6981   FORALLvertex_(qh newvertex_list) {
6982     if (vertex->delridge && !vertex->deleted) {
6983       vertex->delridge= False;
6984       if (qh hull_dim >= 4 && qh_redundant_vertex (vertex)) {
6985 	numrename++;
6986 	if (qh_merge_degenredundant (NULL, NULL, &angle)) {
6987 	  numdegenredun++;
6988 	  goto LABELrestart;
6989 	}
6990       }
6991     }
6992   }
6993   FORALLnew_facets {
6994     if (qh_isnewmerge_(newfacet)) {
6995       qh_clearnewmerge_(newfacet);
6996       if (newfacet->center
6997       && qh_setsize (newfacet->vertices) <= qh hull_dim + qh_MAXnewcentrum) {
6998 	qh_memfree (newfacet->center, qh center_size);
6999 	newfacet->center= NULL;
7000 	newfacet->tested= False;
7001 	FOREACHridge_(newfacet->ridges)
7002 	  ridge->tested= False;
7003 	numcentrums++;
7004       }
7005     }
7006   }
7007   trace1((qh ferr, "qh_reducevertices_centrums: renamed %d shared vertices and %d redundant\nvertices.  Redefined %d centrums and merged %d degen, redundant facets\n",
7008 	  numshare, numrename, numcentrums, numdegenredun));
7009   if (numdegenredun + numcentrums)
7010     return True;
7011   return False;
7012 } /* reducevertices_centrums */
7013 
7014 /*-------------------------------------------------
7015 -redundant_vertex- returns true if detect and rename redundant vertex
7016   vertices have full ->neighbors
7017   only needed if vertex->delridge and hull_dim >= 4
7018 returns:
7019   may add degen facets to facet_mergeset
7020   doesn't change vertex->neighbors or create redundant facets
7021 */
qh_redundant_vertex(vertexT * vertex)7022 vertexT *qh_redundant_vertex (vertexT *vertex) {
7023   vertexT *newvertex= NULL;
7024   setT *vertices, *ridges;
7025 
7026   trace3((qh ferr, "qh_redundant_vertex: check if v%d can be renamed\n", vertex->id));
7027   if ((vertices= qh_neighbor_intersections (vertex))) {
7028     ridges= qh_vertexridges (vertex);
7029     if ((newvertex= qh_find_newvertex (vertex, vertices, ridges)))
7030       qh_renamevertex (vertex, newvertex, ridges, NULL, NULL);
7031     qh_settempfree (&ridges);
7032     qh_settempfree (&vertices);
7033   }
7034   return newvertex;
7035 } /* redundant_vertex */
7036 
7037 /*-------------------------------------------------
7038 -remove_extravertices in non-simplicial facets
7039   returns True if it finds them
7040 */
qh_remove_extravertices(facetT * facet)7041 boolT qh_remove_extravertices (facetT *facet) {
7042   ridgeT *ridge, **ridgep;
7043   vertexT *vertex, **vertexp, *vertexA, **vertexAp;
7044   boolT foundrem= False;
7045 
7046   trace4((qh ferr, "qh_remove_extravertices: test f%d for extra vertices\n",
7047 	  facet->id));
7048   FOREACHvertex_(facet->vertices)
7049     vertex->seen= False;
7050   FOREACHridge_(facet->ridges) {
7051     FOREACHvertexA_(ridge->vertices)
7052       vertexA->seen= True;
7053   }
7054   FOREACHvertex_(facet->vertices) {
7055     if (!vertex->seen) {
7056       foundrem= True;
7057       zinc_(Zremvertex);
7058       qh_setdelsorted (facet->vertices, vertex);
7059       qh_setdel (vertex->neighbors, facet);
7060       if (!qh_setsize (vertex->neighbors)) {
7061 	vertex->deleted= True;
7062 	qh_setappend (&qh del_vertices, vertex);
7063 	zinc_(Zremvertexdel);
7064 	trace2((qh ferr, "qh_remove_extravertices: v%d deleted because it's lost all ridges\n", vertex->id));
7065       }else
7066 	trace3((qh ferr, "qh_remove_extravertices: v%d removed from f%d because it's lost all ridges\n", vertex->id, facet->id));
7067       vertexp--; /*repeat*/
7068     }
7069   }
7070   return foundrem;
7071 } /* remove_extravertices */
7072 
7073 /*-------------------------------------------------
7074 -rename_sharedvertex- detect and rename if shared vertex in facet
7075   vertices have full ->neighbors
7076 returns:
7077   newvertex or NULL
7078   the vertex may still exist in other facets (i.e., a neighbor was pinched)
7079   does not change facet->neighbors, updates vertex->neighbors
7080 notes:
7081   a shared vertex for a facet is only in ridges to one neighbor
7082   this may undo a pinched facet
7083 
7084   it does not catch pinches involving multiple facets.  These appear
7085   to be difficult to detect, since an exhaustive search is too expensive.
7086 */
qh_rename_sharedvertex(vertexT * vertex,facetT * facet)7087 vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet) {
7088   facetT *neighbor, **neighborp, *neighborA= NULL;
7089   setT *vertices, *ridges;
7090   vertexT *newvertex;
7091 
7092   if (qh_setsize (vertex->neighbors) == 2) {
7093     neighborA= (facetT *)SETfirst_(vertex->neighbors);
7094     if (neighborA == facet)
7095       neighborA= (facetT *)SETsecond_(vertex->neighbors);
7096   }else if (qh hull_dim == 3)
7097     return NULL;
7098   else {
7099     qh visit_id++;
7100     FOREACHneighbor_(facet)
7101       neighbor->visitid= qh visit_id;
7102     FOREACHneighbor_(vertex) {
7103       if ((int)neighbor->visitid == qh visit_id) {
7104         if (neighborA)
7105           return NULL;
7106         neighborA= neighbor;
7107       }
7108     }
7109 
7110     if (!neighborA) qhull_fatal(66);
7111 
7112   }
7113   /* the vertex is shared by facet and neighborA */
7114   ridges= qh_settemp (qh TEMPsize);
7115   neighborA->visitid= ++qh visit_id;
7116   qh_vertexridges_facet (vertex, facet, &ridges);
7117   trace2((qh ferr, "qh_rename_sharedvertex: p%d (v%d) is shared by f%d (%d ridges) and f%d\n",
7118     qh_pointid(vertex->point), vertex->id, facet->id, qh_setsize (ridges), neighborA->id));
7119   zinc_(Zintersectnum);
7120   vertices= qh_vertexintersect_new (facet->vertices, neighborA->vertices);
7121   qh_setdel (vertices, vertex);
7122   qh_settemppush (vertices);
7123   if ((newvertex= qh_find_newvertex (vertex, vertices, ridges)))
7124     qh_renamevertex (vertex, newvertex, ridges, facet, neighborA);
7125   qh_settempfree (&vertices);
7126   qh_settempfree (&ridges);
7127   return newvertex;
7128 } /* rename_sharedvertex */
7129 
7130 /*-------------------------------------------------
7131 -renameridgevertex- renames oldvertex as newvertex in ridge
7132 */
qh_renameridgevertex(ridgeT * ridge,vertexT * oldvertex,vertexT * newvertex)7133 void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex) {
7134   int nth= 0, oldnth;
7135   facetT *temp;
7136   vertexT *vertex, **vertexp;
7137 
7138   oldnth= qh_setindex (ridge->vertices, oldvertex);
7139   qh_setdelnthsorted (ridge->vertices, oldnth);
7140   FOREACHvertex_(ridge->vertices) {
7141     if (vertex == newvertex) {
7142       zinc_(Zdelridge);
7143       if (ridge->tested && ridge->nonconvex)
7144 	qh_copynonconvex (ridge);
7145       qh_delridge (ridge);
7146       trace2((qh ferr, "qh_renameridgevertex: ridge r%d deleted.  It contained both v%d and v%d\n",
7147         ridge->id, oldvertex->id, newvertex->id));
7148       return;
7149     }
7150     if (vertex->id < newvertex->id)
7151       break;
7152     nth++;
7153   }
7154   qh_setaddnth(&ridge->vertices, nth, newvertex);
7155   if (abs(oldnth - nth)%2) {
7156     trace3((qh ferr, "qh_renameridgevertex: swapped the top and bottom of ridge r%d\n",
7157 	    ridge->id));
7158     temp= ridge->top;
7159     ridge->top= ridge->bottom;
7160     ridge->bottom= temp;
7161   }
7162 } /* renameridgevertex */
7163 
7164 
7165 /*-------------------------------------------------
7166 -renamevertex- renames oldvertex as newvertex in ridges
7167   oldvertex may still exist afterwards
7168   gives oldfacet/neighborA if shared between facets
7169 notes:
7170   can not change neighbors of newvertex (since it's a subset)
7171 */
qh_renamevertex(vertexT * oldvertex,vertexT * newvertex,setT * ridges,facetT * oldfacet,facetT * neighborA)7172 void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges, facetT *oldfacet, facetT *neighborA) {
7173   facetT *neighbor, **neighborp;
7174   ridgeT *ridge, **ridgep;
7175   boolT istrace= False;
7176 
7177   if (qh IStracing >= 2 || oldvertex->id == qh tracevertex_id ||
7178 	newvertex->id == qh tracevertex_id)
7179     istrace= True;
7180   FOREACHridge_(ridges)
7181     qh_renameridgevertex (ridge, oldvertex, newvertex);
7182   if (qh CHECKfrequently) {
7183     FOREACHneighbor_(oldvertex) {
7184       qh_checkridge_boundary (neighbor);
7185     }
7186   }
7187   if (!oldfacet) {
7188     zinc_(Zrenameall);
7189     if (istrace)
7190       fprintf (qh ferr, "qh_renamevertex: renamed v%d to v%d in several facets\n",
7191                oldvertex->id, newvertex->id);
7192     FOREACHneighbor_(oldvertex) {
7193       qh_maydropneighbor (neighbor);
7194       qh_setdelsorted (neighbor->vertices, oldvertex);
7195       if (qh_remove_extravertices (neighbor))
7196         neighborp--; /* neighbor may be deleted */
7197     }
7198     if (!oldvertex->deleted) {
7199       oldvertex->deleted= True;
7200       qh_setappend (&qh del_vertices, oldvertex);
7201     }
7202   }else if (qh_setsize (oldvertex->neighbors) == 2) {
7203     zinc_(Zrenameshare);
7204     if (istrace)
7205       fprintf (qh ferr, "qh_renamevertex: renamed v%d to v%d in oldfacet f%d\n",
7206                oldvertex->id, newvertex->id, oldfacet->id);
7207     FOREACHneighbor_(oldvertex)
7208       qh_setdelsorted (neighbor->vertices, oldvertex);
7209     oldvertex->deleted= True;
7210     qh_setappend (&qh del_vertices, oldvertex);
7211   }else {
7212     zinc_(Zrenamepinch);
7213     if (istrace || qh IStracing)
7214       fprintf (qh ferr, "qh_renamevertex: renamed pinched v%d to v%d between f%d and f%d\n",
7215                oldvertex->id, newvertex->id, oldfacet->id, neighborA->id);
7216     qh_setdelsorted (oldfacet->vertices, oldvertex);
7217     qh_setdel (oldvertex->neighbors, oldfacet);
7218     qh_remove_extravertices (neighborA);
7219   }
7220 } /* renamevertex */
7221 
7222 
7223 /*-----------------------------------------
7224 -test_appendmerge- tests facet/neighbor and appends to mergeset if nonconvex
7225   sets facet->center as needed
7226 returns:
7227   true if appends to mergeset
7228     sets 'acoplanar' if angle coplanar
7229 */
qh_test_appendmerge(facetT * facet,facetT * neighbor)7230 boolT qh_test_appendmerge (facetT *facet, facetT *neighbor) {
7231   realT dist, dist2= -REALmax, angle;
7232   boolT isconcave= False, iscoplanar= False;
7233   mergeT *merge;
7234 
7235   angle= qh_getangle(facet->normal, neighbor->normal);
7236   zinc_(Zangletests);
7237   if (angle > qh cos_max) {
7238     zinc_(Zcoplanarangle);
7239     merge= qh_appendmergeset(facet, neighbor, &angle);
7240     merge->anglecoplanar= True;
7241     trace2((qh ferr, "qh_test_appendmerge: coplanar angle %4.4g between f%d and f%d\n",
7242        angle, facet->id, neighbor->id));
7243     return True;
7244   }else {
7245     if (!facet->center)
7246       facet->center= qh_getcentrum (facet);
7247     zzinc_(Zcentrumtests);
7248     qh_distplane(facet->center, neighbor, &dist);
7249     if (dist > qh centrum_radius)
7250       isconcave= True;
7251     else {
7252       if (dist > -qh centrum_radius)
7253 	iscoplanar= True;
7254       if (!neighbor->center)
7255         neighbor->center= qh_getcentrum (neighbor);
7256       zinc_(Zcentrumtests);
7257       qh_distplane(neighbor->center, facet, &dist2);
7258       if (dist2 > qh centrum_radius)
7259         isconcave= True;
7260       else if (dist2 > -qh centrum_radius)
7261         iscoplanar= True;
7262     }
7263     if (isconcave) {
7264       zinc_(Zconcaveridge);
7265       angle += qh_ANGLEconcave + 0.5;
7266       qh_appendmergeset(facet, neighbor, &angle);
7267       trace0((qh ferr, "qh_test_appendmerge: concave f%d to f%d dist %4.4g and reverse dist %4.4g angle %4.4g\n",
7268 	      facet->id, neighbor->id, dist, dist2, angle));
7269       return True;
7270     }else if (iscoplanar) {
7271       zinc_(Zcoplanarcentrum);
7272       qh_appendmergeset(facet, neighbor, &angle);
7273       trace2((qh ferr, "qh_test_appendmerge: coplanar f%d to f%d dist %4.4g, reverse dist %4.4g angle %4.4g\n",
7274 	      facet->id, neighbor->id, dist, dist2, angle));
7275       return True;
7276     }
7277   }
7278   return False;
7279 } /* test_appendmerge */
7280 
7281 
7282 /*------------------------------------------
7283 -tracemerging- print trace message if active
7284 */
qh_tracemerging(const char * string)7285 void qh_tracemerging (const char *string) {
7286   realT cpu;
7287   time_t timedata;
7288   struct tm *tp;
7289 
7290   if (qh REPORTfreq && (zzval_(Ztotmerge) > qh mergereport+qh REPORTfreq/2)) {
7291     qh mergereport= zzval_(Ztotmerge);
7292     time (&timedata);
7293     tp= localtime (&timedata);
7294     cpu= clock();
7295     cpu /= qh_SECticks;
7296     zinc_(Zdistio);
7297     fprintf (qh ferr, "\n\
7298 At %d:%d:%d & %2.5g CPU secs, qhull has merged %d facets.  The hull\n\
7299   contains %d facets and %d vertices. p%d was the last point.\n",
7300       tp->tm_hour, tp->tm_min, tp->tm_sec, cpu,
7301       zzval_(Ztotmerge), qh num_facets - qh num_visible,
7302       qh num_vertices-qh_setsize (qh del_vertices), qh furthest_id);
7303   }
7304 } /* tracemerging */
7305 
7306 /*------------------------------------------
7307 -vertexridges- return temporary set of ridges adjacent to a vertex
7308   vertex->neighbors defined
7309   uses qh visit_id
7310   does not include implicit ridges for simplicial facets
7311 */
qh_vertexridges(vertexT * vertex)7312 setT *qh_vertexridges (vertexT *vertex) {
7313   facetT *neighbor, **neighborp;
7314   setT *ridges= qh_settemp (qh TEMPsize);
7315   int size;
7316 
7317   qh visit_id++;
7318   FOREACHneighbor_(vertex)
7319     neighbor->visitid= qh visit_id;
7320   FOREACHneighbor_(vertex) {
7321     if (*neighborp)   /* no new ridges in last neighbor */
7322       qh_vertexridges_facet (vertex, neighbor, &ridges);
7323   }
7324   if (qh PRINTstatistics || qh IStracing) {
7325     size= qh_setsize (ridges);
7326     zinc_(Zvertexridge);
7327     zadd_(Zvertexridgetot, size);
7328     zmax_(Zvertexridgemax, size);
7329     trace3((qh ferr, "qh_vertexridges: found %d ridges for v%d\n",
7330              size, vertex->id));
7331   }
7332   return ridges;
7333 } /* vertexridges */
7334 
7335 /*------------------------------------------
7336 -vertexridges_facet- add adjacent ridges for vertex in facet
7337   skips ridges if neighbor->visitid< visit_id
7338 returns:
7339   sets facet->visitid to visit_id-1
7340 */
qh_vertexridges_facet(vertexT * vertex,facetT * facet,setT ** ridges)7341 void qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges) {
7342   ridgeT *ridge, **ridgep;
7343   facetT *neighbor;
7344 
7345   FOREACHridge_(facet->ridges) {
7346     neighbor= otherfacet_(ridge, facet);
7347     if ((int)neighbor->visitid == qh visit_id
7348     && qh_setin (ridge->vertices, vertex))
7349       qh_setappend (ridges, ridge);
7350   }
7351   facet->visitid= qh visit_id-1;
7352 } /* vertexridges_facet */
7353 
7354 
7355 
7356 
7357 /*************************************************************************/
7358 /****************** implementation code from global.c ********************/
7359 /*************************************************************************/
7360 
7361 /* global.c -- contains all the globals of the qhull application
7362 
7363    see README
7364 
7365    see qhull.h for qh globals and function prototypes
7366 
7367    see qhull_a.h for internal functions
7368 
7369    copyright (c) 1993-1994, The Geometry Center
7370 */
7371 
7372 #if qh_QHpointer
7373 qhT *qh_qh=  NULL;
7374 #else
7375 qhT qh_qh; /*= {0};*/ /* remove "= {0}" if this causes a compiler error.  Also
7376 		     qh_qhstat in stat.c and qhmem in mem.c.  */
7377 #endif
7378 
7379 /* ------------Simple all purpose error report-------------*/
7380 
7381 #ifdef GAMBIT_EXCEPTIONS
~ErrorInQhull()7382 ErrorInQhull::~ErrorInQhull() { }
7383 
GetDescription(void) const7384 std::string ErrorInQhull::GetDescription(void) const
7385 {
7386   return "Error somewhere in Qhull";
7387 }
7388 #endif
7389 
qhull_fatal(int errorno)7390 void qhull_fatal(int errorno)
7391 {
7392 #ifdef GAMBIT_EXCEPTIONS
7393   throw ErrorInQhull();
7394 #endif
7395 
7396   printf("\nError number %d in qhull.\n", errorno);
7397   exit(0);
7398 }
7399 
7400 
7401 /*-------------------------------------------
7402 -appendprint- append output format to qh PRINTout unless already defined
7403 */
qh_appendprint(int format)7404 void qh_appendprint (int format) {
7405   int i;
7406 
7407   for (i=0; i < qh_PRINTEND; i++) {
7408     if (qh PRINTout[i] == format)
7409       break;
7410     if (!qh PRINTout[i]) {
7411       qh PRINTout[i]= format;
7412       break;
7413     }
7414   }
7415 } /* appendprint */
7416 
7417 /*-------------------------------------------
7418 -freebuffers- free up global memory buffers
7419   must match initbuffers()
7420 */
7421 
qh_freebuffers(void)7422 void qh_freebuffers (void) {
7423 
7424   trace5((qh ferr, "qh_freebuffers: freeing up global memory buffers\n"));
7425   qh_memfree (qh NEARzero, qh hull_dim * sizeof(realT));
7426   qh_memfree (qh lower_threshold, (qh input_dim+1) * sizeof(realT));
7427   qh_memfree (qh upper_threshold, (qh input_dim+1) * sizeof(realT));
7428   qh_memfree (qh lower_bound, (qh input_dim+1) * sizeof(realT));
7429   qh_memfree (qh upper_bound, (qh input_dim+1) * sizeof(realT));
7430   qh_memfree (qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
7431   qh_memfree (qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
7432   qh_setfree (&qh hash_table);
7433   qh_setfree (&qh other_points);
7434   qh_setfree (&qh del_vertices);
7435   /* qh facet_mergeset is a temp */
7436   qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
7437   qh lower_bound= qh upper_bound= NULL;
7438   qh gm_matrix= NULL;
7439   qh gm_row= NULL;
7440   if (qh line)
7441     free (qh line);
7442   if (qh first_point && qh POINTSmalloc)
7443     free(qh first_point);
7444   trace5((qh ferr, "qh_freebuffers: finished\n"));
7445 } /* freebuffers */
7446 
7447 
7448 /*-------------------------------------------
7449 -freeqhull- free global memory
7450   if allmem, frees all allocated data structures
7451   else, frees all long memory
7452     rest of memory freed by qh_memfreeshort();
7453 */
qh_freeqhull(boolT allmem)7454 void qh_freeqhull (boolT allmem) {
7455   facetT *facet;
7456   vertexT *vertex;
7457   ridgeT *ridge, **ridgep;
7458   mergeT *merge, **mergep;
7459 
7460   trace1((qh ferr, "qh_freeqhull: free global memory\n"));
7461   qh NOerrexit= True;  /* no more setjmp */
7462   if (allmem) {
7463     qh_clearcenters (qh_none);
7464     while ((vertex= qh vertex_list)) {
7465       if (vertex->next)
7466         qh_delvertex (vertex);
7467       else {
7468         qh_memfree (vertex, sizeof(vertexT));
7469         qh vertex_list= NULL;
7470       }
7471     }
7472   }else if (qh VERTEXneighbors) {
7473     FORALLvertices
7474       qh_setfreelong (&(vertex->neighbors));
7475   }
7476   if (allmem) {
7477     FORALLfacets {
7478       if (!facet->visible) {
7479 	FOREACHridge_(facet->ridges)
7480 	  ridge->seen= False;
7481       }
7482     }
7483     FORALLfacets {
7484       FOREACHridge_(facet->ridges)
7485         ridge->seen ^= True;
7486     }
7487     while ((facet= qh facet_list)) {
7488       FOREACHridge_(facet->ridges) {
7489         if (ridge->seen) {
7490           qh_setfree(&(ridge->vertices));
7491           qh_memfree(ridge, sizeof(ridgeT));
7492         }else
7493           ridge->seen= True;
7494       }
7495       if (facet->next)
7496         qh_delfacet (facet);
7497       else {
7498         qh_memfree (facet, sizeof(facetT));
7499         qh facet_list= NULL;
7500       }
7501     }
7502   }else {
7503     FORALLfacets {
7504       qh_setfreelong (&(facet->outsideset));
7505       qh_setfreelong (&(facet->coplanarset));
7506       if (!facet->simplicial) {
7507         qh_setfreelong (&(facet->neighbors));
7508         qh_setfreelong (&(facet->ridges));
7509         qh_setfreelong (&(facet->vertices));
7510       }
7511     }
7512   }
7513   qh_setfree (&qh hash_table);
7514   FOREACHmerge_(qh facet_mergeset)  /* usually empty */
7515     qh_memfree (merge, sizeof(mergeT));
7516   qh_freebuffers();
7517   qh_freestatistics();
7518   qh_settempfree_all();
7519 #if qh_QHpointer
7520   free (qh_qh);
7521   qh_qh= NULL;
7522 #endif
7523 } /* freeqhull */
7524 
7525 
7526 /*---------------------------------------------
7527 -init_qhull_command- build qhull_command from argc/argv
7528 */
qh_init_qhull_command(int argc,char * argv[])7529 void qh_init_qhull_command(int argc, char *argv[]) {
7530   int i;
7531 
7532   strcpy (qh qhull_command, argv[0]);
7533   for (i=1; i<argc; i++) {
7534     if (strlen (qh qhull_command) + strlen(argv[i]) + 1 < sizeof(qh qhull_command)) {
7535       strcat (qh qhull_command, " ");
7536       strcat (qh qhull_command, argv[i]);
7537     }else qhull_fatal(67);
7538 
7539   }
7540 } /* init_qhull_command */
7541 
7542 /*---------------------------------------------
7543 -initflags- set flags and initialized constants from command line
7544   strips off first word
7545   see 'prompt' in unix.c for documentation
7546   see also initthresholds
7547   strtol/strtod may or may not skip trailing spaces
7548   does not reset any flags
7549     use the qh structure to change flags during execution of qhull
7550 
7551 */
7552 
qh_initflags(char * command)7553 void qh_initflags(char *command) {
7554   int k;
7555   char *s= command, *t, *prev_s;
7556 
7557   while (*s && !isspace(*s))  /* need a better convention */
7558     s++;
7559   while (*s) {
7560     while (*s && isspace(*s))
7561       s++;
7562     if (*s == '-')
7563       s++;
7564     prev_s= s;
7565     switch (*s++) {
7566     case 'd':
7567       qh DELAUNAY= True;
7568       break;
7569     case 'f':
7570       qh_appendprint (qh_PRINTfacets);
7571       break;
7572     case 'i':
7573       qh_appendprint (qh_PRINTincidences);
7574       break;
7575     case 'm':
7576       qh_appendprint (qh_PRINTmathematica);
7577       break;
7578     case 'n':
7579       qh_appendprint (qh_PRINTnormals);
7580       break;
7581     case 'o':
7582       qh_appendprint (qh_PRINToff);
7583       break;
7584     case 'p':
7585       qh_appendprint (qh_PRINTpoints);
7586       break;
7587     case 's':
7588       qh PRINTsummary= True;
7589       break;
7590     case 'v':
7591       qh VORONOI= True;
7592       qh DELAUNAY= True;
7593       break;
7594     case 'A':
7595       if (!isdigit(*s) && *s != '.' && *s != '-')
7596 	fprintf(qh ferr, "qhull warning: no maximum cosine angle given for option A.  Ignored.\n");
7597       else {
7598 	if (*s == '-') {
7599 	  qh premerge_cos= -qh_strtod (s, &s);
7600 	  qh PREmerge= True;
7601 	}else {
7602 	  qh postmerge_cos= qh_strtod (s, &s);
7603 	  qh POSTmerge= True;
7604 	}
7605 	qh MERGING= True;
7606       }
7607       break;
7608     case 'C':
7609       if (!isdigit(*s) && *s != '.' && *s != '-')
7610 	fprintf(qh ferr, "qhull warning: no centrum radius given for option C.  Ignored.\n");
7611       else {
7612 	if (*s == '-') {
7613 	  qh premerge_centrum= -qh_strtod (s, &s);
7614 	  qh PREmerge= True;
7615 	}else {
7616 	  qh postmerge_centrum= qh_strtod (s, &s);
7617 	  qh POSTmerge= True;
7618 	}
7619 	qh MERGING= True;
7620       }
7621       break;
7622     case 'E':
7623       if (*s == '-')
7624 	fprintf(qh ferr, "qhull warning: negative maximum roundoff given for option A.  Ignored.\n");
7625       else if (!isdigit(*s))
7626 	fprintf(qh ferr, "qhull warning: no maximum roundoff given for option E.  Ignored.\n");
7627       else {
7628 	qh DISTround= qh_strtod (s, &s);
7629 	qh SETroundoff= True;
7630       }
7631       break;
7632     case 'R':
7633       if (!isdigit(*s))
7634 	fprintf(qh ferr, "qhull warning: no random perturbation given for option R.  Ignored\n");
7635       else {
7636 	qh RANDOMfactor= qh_strtod (s, &s);
7637         qh RANDOMdist= True;
7638       }
7639       break;
7640     case 'V':
7641       if (!isdigit(*s) && *s != '-')
7642 	fprintf(qh ferr, "qhull warning: no distance given for option V.  Ignored\n");
7643       else
7644 	qh MINvisible= qh_strtod (s, &s);
7645       break;
7646     case 'W':
7647       if (*s == '-')
7648 	fprintf(qh ferr, "qhull warning: negative width for option W.  Ignored.\n");
7649       else if (!isdigit(*s))
7650 	fprintf(qh ferr, "qhull warning: no hull width given for option W.  Ignored\n");
7651       else {
7652 	qh MINoutside= qh_strtod (s, &s);
7653         qh APPROXhull= True;
7654       }
7655       break;
7656     /************  sub menus ***************/
7657     case 'G':
7658       qh_appendprint (qh_PRINTgeom);
7659       while (*s && !isspace(*s)) {
7660 	switch(*s++) {
7661         case 'a':
7662           qh PRINTdots= True;
7663           break;
7664         case 'c':
7665           qh PRINTcentrums= True;
7666           break;
7667 	case 'h':
7668 	  qh DOintersections= True;
7669 	  break;
7670 	case 'i':
7671 	  qh PRINTinner= True;
7672 	  break;
7673 	case 'n':
7674 	  qh PRINTnoplanes= True;
7675 	  break;
7676 	case 'o':
7677 	  qh PRINTouter= True;
7678 	  break;
7679 	case 'p':
7680 	  qh PRINTcoplanar= True;
7681 	  break;
7682 	case 'r':
7683 	  qh PRINTridges= True;
7684 	  break;
7685 	case 'v':
7686 	  qh PRINTspheres= True;
7687 	  break;
7688 	case 'D':
7689 	  if (!isdigit (*s))
7690 	    fprintf (qh ferr, "qhull input error: missing dimension for 'GD' option\n");
7691 	  else
7692   	    qh DROPdim= qh_strtol (s, &s);
7693 	  break;
7694 	default:
7695 	  s--;
7696 	  fprintf (qh ferr, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
7697 	  while (*++s && !isspace(*s));
7698 	  break;
7699 	}
7700       }
7701       break;
7702     case 'P':
7703       while (*s && !isspace(*s)) {
7704 	switch(*s++) {
7705 	case 'd': case 'D':
7706 	  qh_strtol (s, &s);
7707 	  if (*s == ':') {
7708 	    ++s;
7709 	    qh_strtod (s, &s);
7710 	  }
7711 	  break;
7712         case 'g':
7713           qh PRINTgood= True;
7714           break;
7715         case 'G':
7716           qh PRINTneighbors= True;
7717           break;
7718         case 'o':
7719           qh FORCEoutput= True;
7720           break;
7721         case 'p':
7722           qh PRINTprecision= False;
7723           break;
7724 	default:
7725 	  s--;
7726 	  fprintf (qh ferr, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[-1]);
7727 	  while (*++s && !isspace(*s));
7728 	  break;
7729 	}
7730       }
7731       break;
7732     case 'Q':
7733       while (*s && !isspace(*s)) {
7734 	switch(*s++) {
7735 	case 'b': case 'B':
7736 	  k= qh_strtol (s, &s);
7737 	  t= NULL;
7738 	  if (*s == ':' && qh_strtod(++s, &s) == 0.0) {
7739 	    t= s;            /* need true dimension for memory allocation */
7740 	    while (*t && !isspace(*t)) {
7741 	      if (toupper(*t++) == 'B'
7742 	       && k == qh_strtol (t, &t)
7743 	       && *t++ == ':'
7744 	       && qh_strtod(t, &t) == 0.0) {
7745 	        qh PROJECTinput++;
7746 	        trace2((qh ferr, "qh_initflags: project dimension %d\n", k));
7747 	        break;
7748 	      }
7749 	    }
7750   	  }
7751 	  if (!t || !isspace(*t))
7752 	    qh SCALEinput= True;
7753 	  break;
7754 	case 'c':
7755 	  qh KEEPcoplanar= True;
7756 	  break;
7757 	case 'f':
7758 	  qh BESToutside= True;
7759 	  break;
7760 	case 'g':
7761 	  qh ONLYgood= True;
7762 	  break;
7763 	case 'i':
7764 	  qh KEEPinside= True;
7765 	  break;
7766 	case 'm':
7767 	  qh ONLYmax= True;
7768 	  break;
7769 	case 'r':
7770 	  qh RANDOMoutside= True;
7771 	  break;
7772 	case 's':
7773 	  qh ALLpoints= True;
7774 	  break;
7775 	case 'v':
7776 	  qh VIRTUALmemory= True;
7777 	  break;
7778 	case 'G':
7779 	  if (qh GOODpoint) {
7780 	    fprintf (qh ferr, "qhull warning: good point already defined for QGn.  Ignored\n");
7781             qh_strtol(s, &s);
7782           }else if (!isdigit(*s) && (*s != '-'))
7783 	    fprintf (qh ferr, "qhull warning: no good point id given for option QGn.  Ignored\n");
7784 	  else if (*s == '-')
7785  	    qh GOODpoint= qh_strtol(s, &s)-1;
7786 	  else
7787  	    qh GOODpoint= qh_strtol(s, &s)+1;
7788 	  break;
7789 	case 'R':
7790           if (!isdigit(*s) && *s != '-')
7791 	    fprintf (qh ferr, "qhull warning: missing random seed for option QRn.  Ignored\n");
7792 	  else
7793  	    qh ROTATErandom= qh_strtol(s, &s);
7794 	  break;
7795 	case 'V':
7796 	  if (qh GOODvertex) {
7797 	    fprintf (qh ferr, "qhull warning: good vertex already defined for QV.  Ignored\n");
7798             qh_strtol(s, &s);
7799           }else if (!isdigit(*s) && (*s != '-'))
7800 	    fprintf (qh ferr, "qhull warning: no good point id given for QV.  Ignored\n");
7801 	  else if (*s == '-')
7802  	    qh GOODvertex= qh_strtol(s, &s)-1;
7803 	  else
7804  	    qh GOODvertex= qh_strtol(s, &s)+1;
7805 	  break;
7806 	default:
7807 	  fprintf (qh ferr, "qhull warning: unknown 'Q' qhull option %c, rest ignored\n", (int)s[-1]);
7808 	  while (*++s && !isspace(*s));
7809 	  break;
7810 	}
7811       }
7812       break;
7813     case 'T':
7814       while (*s && !isspace(*s)) {
7815 	if (isdigit(*s) || *s == '-')
7816 	  qh IStracing= qh_strtol(s, &s);
7817 	else switch(*s++) {
7818 	case 'c':
7819 	  qh CHECKfrequently= True;
7820 	  break;
7821 	case 's':
7822 	  qh PRINTstatistics= True;
7823 	  break;
7824 	case 'v':
7825 	  qh VERIFYoutput= True;
7826 	  break;
7827 	case 'C':
7828 	  if (!isdigit(*s))
7829 	    fprintf (qh ferr, "qhull warning: no point given for trace option C.  Ignored\n");
7830 	  else
7831 	    qh STOPcone= qh_strtol (s, &s)+1;
7832 	  break;
7833 	case 'F':
7834 	  if (!isdigit(*s))
7835 	    fprintf (qh ferr, "qhull warning: no count of new facets for trace option P.  Ignored\n");
7836 	  else
7837 	    qh REPORTfreq= qh_strtol (s, &s);
7838 	  break;
7839 	case 'P':
7840 	  if (!isdigit(*s))
7841 	    fprintf (qh ferr, "qhull warning: no point given for trace option P.  Ignored\n");
7842 	  else
7843 	    qh TRACEpoint= qh_strtol (s, &s);
7844 	  break;
7845 	case 'M':
7846 	  if (!isdigit(*s))
7847 	    fprintf (qh ferr, "qhull warning: no merge given for trace option M.  Ignored\n");
7848 	  else
7849 	    qh TRACEmerge= qh_strtol (s, &s);
7850 	  break;
7851 	case 'V':
7852 	  if (!isdigit(*s) && *s != '-')
7853 	    fprintf (qh ferr, "qhull warning: no point given for trace option V.  Ignored\n");
7854 	  else if (*s == '-')
7855 	    qh STOPpoint= qh_strtol (s, &s)-1;
7856 	  else
7857 	    qh STOPpoint= qh_strtol (s, &s)+1;
7858 	  break;
7859 	case 'W':
7860 	  if (!isdigit(*s))
7861 	    fprintf (qh ferr, "qhull warning: no max width given for trace option D.  Ignored\n");
7862 	  else
7863  	    qh TRACEdist= (realT) qh_strtod (s, &s);
7864 	  break;
7865 	default:
7866 	  fprintf (qh ferr, "qhull warning: unknown 'T' trace option %c, rest ignored\n", (int)s[-1]);
7867 	  while (*++s && !isspace(*s));
7868 	  break;
7869 	}
7870       }
7871       break;
7872     default:
7873       fprintf (qh ferr, "qhull warning: unknown flag %c (%x)\n", (int)s[-1],
7874 	       (int)s[-1]);
7875       break;
7876     }
7877     if (s-1 == prev_s && *s && !isspace(*s)) {
7878       fprintf (qh ferr, "qhull warning: missing space after flag %c (%x); reserved for menu. Skipped.\n",
7879 	       (int)*prev_s, (int)*prev_s);
7880       while (*s && !isspace(*s))
7881 	s++;
7882     }
7883   }
7884 } /* initflags */
7885 
7886 
7887 /*-------------------------------------------
7888 -initqhull_buffers- initialize global memory buffers
7889   must match freebuffers()
7890 */
qh_initqhull_buffers(void)7891 void qh_initqhull_buffers (void) {
7892   int k;
7893 
7894   qh TEMPsize= (qhmem.LASTsize - sizeof (setT))/SETelemsize;
7895   qh other_points= qh_setnew (qh TEMPsize);
7896   qh del_vertices= qh_setnew (qh TEMPsize);
7897   qh NEARzero= (realT *)qh_memalloc(qh hull_dim * sizeof(realT));
7898   qh lower_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
7899   qh upper_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
7900   qh lower_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
7901   qh upper_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
7902   for(k= qh input_dim+1; k--; ) {
7903     qh lower_threshold[k]= -REALmax;
7904     qh upper_threshold[k]= REALmax;
7905     qh lower_bound[k]= -REALmax;
7906     qh upper_bound[k]= REALmax;
7907   }
7908   qh gm_matrix= (coordT *)qh_memalloc((qh hull_dim+1) * qh hull_dim * sizeof(coordT));
7909   qh gm_row= (coordT **)qh_memalloc((qh hull_dim+1) * sizeof(coordT *));
7910 } /* initqhull_buffers */
7911 
7912 /*---------------------------------------------
7913 -initqhull_globals- initialize globals
7914   ismalloc set if points were malloc'd and qhull should free at end
7915 returns:
7916   sets qh first_point, num_points, input_dim, hull_dim and others
7917   modifies hull_dim if ((DELAUNAY and PROJECTdelaunay) or PROJECTinput)
7918   seeds random number generator (seed=1 if tracing)
7919   adjust user flags as needed
7920   also checks hull_dim dependencies and constants
7921 */
qh_initqhull_globals(coordT * points,int numpoints,int dim,boolT ismalloc)7922 void qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc) {
7923   int seed, pointsneeded, extra= 0, i, randi;
7924   boolT printgeom= False, printother= False, printmath= False;
7925   realT randr;
7926 
7927   time_t timedata;
7928 
7929   trace0((qh ferr, "qh_initqhull_globals: for %s | %s\n", qh rbox_command,
7930       qh qhull_command));
7931   qh POINTSmalloc= ismalloc;
7932   qh first_point= points;
7933   qh num_points= numpoints;
7934   qh hull_dim= qh input_dim= dim;
7935   if (qh DELAUNAY) {
7936     qh KEEPcoplanar= True;
7937     qh KEEPinside= True;
7938   }
7939   if (qh PREmerge) {
7940     /* e.g., rbox 1000 t W8e-6 | qhull C-0, can drop an outside point, since
7941        qh_findbest doesn't detect nearly coplanar when point beyond facets */
7942     qh BESToutside= True;
7943   }
7944   if (qh MERGING)
7945     qh CENTERtype= qh_centrum;
7946   else if (qh VORONOI)
7947     qh CENTERtype= qh_voronoi;
7948   if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay)) {
7949     qh hull_dim -= qh PROJECTinput;
7950     if (qh DELAUNAY) {
7951       qh hull_dim++;
7952       extra= 1;
7953     }
7954   }
7955 
7956   if (qh hull_dim <= 1) qhull_fatal(68);
7957 
7958   trace2((qh ferr, "qh_initqhull_globals: initialize globals.  dim %d numpoints %d malloc? %d projected %d to hull_dim %d\n",
7959 	dim, numpoints, ismalloc, qh PROJECTinput, qh hull_dim));
7960   qh normal_size= qh hull_dim * sizeof(coordT);
7961   qh center_size= qh normal_size - sizeof(coordT);
7962   pointsneeded= qh hull_dim+1;
7963   if (qh GOODpoint)
7964     pointsneeded++;
7965   if (qh GOODpoint > 0)
7966     qh GOODpointp= qh_point (qh GOODpoint-1);
7967   else if (qh GOODpoint < 0)
7968     qh GOODpointp= qh_point (-qh GOODpoint-1);
7969   if (qh GOODvertex > 0)
7970     qh GOODvertexp= qh_point (qh GOODvertex-1);
7971   else if (qh GOODvertex < 0)
7972     qh GOODvertexp= qh_point (-qh GOODvertex-1);
7973 
7974   if ((qh GOODpointp
7975        && (qh GOODpointp < qh first_point
7976 	   || qh GOODpointp > qh_point (qh num_points-1)))
7977     || (qh GOODvertexp
7978 	&& (qh GOODvertexp < qh first_point
7979 	    || qh GOODvertexp > qh_point (qh num_points-1)))) qhull_fatal(69);
7980 
7981   if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
7982     qh TRACElevel= (qh IStracing? qh IStracing : 3);
7983     qh IStracing= 0;
7984   }
7985   if (qh ROTATErandom == 0 || qh ROTATErandom == -1) {
7986     seed= time (&timedata);
7987     qh ROTATErandom= seed;
7988   }else if (qh ROTATErandom > 0)
7989     seed= qh ROTATErandom;
7990   else
7991     seed= 1;
7992   qh_RANDOMseed_(seed);
7993   randr= 0.0;
7994   for (i= 1000; i--; ) {
7995     randi= qh_RANDOMint;
7996     randr += randi;
7997 
7998     /* DEBUG */
7999     /* - I reset qh_RANDOMmax in qhull.h, but not intelligently.
8000        Expect more trouble inn the future.
8001     printf("qh_RANDOMmax is %d.\n", qh_RANDOMmax);
8002     printf("randi is %d.\n", randi); */
8003 
8004 
8005     if (randi > qh_RANDOMmax) qhull_fatal(70);
8006 
8007   }
8008   if (randr/1000 < qh_RANDOMmax/10)
8009     fprintf (qh ferr, "qhull configuration warning (initqhull_globals): average of 1000 randoms %.2g much less than expected (%.2g).  Is qh_RANDOMmax wrong?\n",
8010 	     randr/1000, (double) (qh_RANDOMmax/2));
8011   qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax;
8012   qh RANDOMb= 1.0 - qh RANDOMfactor;
8013 
8014 #ifndef __BCC55__
8015   // This condition is always false under BCC55
8016   if (qh_HASHfactor < 1.1) qhull_fatal(71);
8017 #endif  // __BCC55__
8018 
8019   if (numpoints+extra < pointsneeded) qhull_fatal(72);
8020 
8021   for (i= qh_PRINTEND; i--; ) {
8022     if (qh PRINTout[i] == qh_PRINTmathematica)
8023       printmath= True;
8024     if (qh PRINTout[i] == qh_PRINTgeom)
8025       printgeom= True;
8026     else if (qh PRINTout[i])
8027       printother= True;
8028   }
8029   if (printmath && qh hull_dim > 3) qhull_fatal(73);
8030 
8031   if (printgeom) {
8032 
8033     if (qh hull_dim > 4) qhull_fatal(74);
8034 
8035     if (qh PRINTnoplanes && !(qh PRINTcoplanar + qh PRINTcentrums
8036      + qh PRINTdots + qh PRINTspheres + qh DOintersections + qh PRINTridges))
8037       qhull_fatal(75);
8038 
8039     if (qh VORONOI && (qh hull_dim > 3 || qh DROPdim >= 0)) qhull_fatal(76);
8040 
8041     if (qh hull_dim == 4 && qh DROPdim == -1 &&
8042 	(qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
8043       fprintf (qh ferr, "qhull input warning: coplanars, vertices, and centrums output not\n\
8044 available for 4-d output (ignored).  Could use 'GDn' instead.\n");
8045       qh PRINTcoplanar= qh PRINTspheres= qh PRINTcentrums= False;
8046     }
8047   }
8048   qh PRINTdim= qh hull_dim;
8049   if (qh DROPdim >=0) {    /* after Geomview checks */
8050     if (qh DROPdim < qh hull_dim) {
8051       qh PRINTdim--;
8052       if (printother || qh hull_dim < 3)
8053         fprintf (qh ferr, "qhull input warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh DROPdim);
8054     }else
8055       qh DROPdim= -1;
8056   }else if (qh VORONOI) {
8057     qh DROPdim= qh hull_dim-1;
8058     qh PRINTdim= qh hull_dim-1;
8059   }
8060 } /* initqhull_globals */
8061 
8062 /*-----------------------------------------------------
8063 -initqhull_mem- initialize mem.c for qhull
8064   qh.hull_dim and normal_size determines some of the allocation sizes
8065   if qh MERGING, includes ridgeT
8066 returns:
8067   mem.c already for memalloc/memfree (errors if called beforehand)
8068 notes:
8069   the user can add up to 10 additional sizes for quick allocation (increase numsizes)
8070 */
qh_initqhull_mem(void)8071 void qh_initqhull_mem (void) {
8072   int numsizes;
8073   int i;
8074 
8075   numsizes= 7+10;
8076   qh_meminitbuffers (qh IStracing, qh_MEMalign, numsizes,
8077                      qh_MEMbufsize,qh_MEMinitbuf);
8078   qh_memsize(sizeof(vertexT));
8079   if (qh MERGING)
8080     qh_memsize(sizeof(ridgeT));
8081   qh_memsize(sizeof(facetT));
8082   qh_memsize(sizeof(hashentryT));
8083   i= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;  /* ridge.vertices */
8084   qh_memsize(i);
8085   qh_memsize(qh normal_size);        /* normal */
8086   i += SETelemsize;                 /* facet.vertices, .ridges, .neighbors */
8087   qh_memsize(i);
8088   /*  qh_user_memsizes(); - THIS DID NOTHING */
8089   qh_memsetup();
8090 } /* initqhull_mem */
8091 
8092 /*-------------------------------------------
8093 -initqhull_start -- start initialization of qhull
8094   inits statistics
8095 */
qh_initqhull_start(FILE * infile,FILE * outfile,FILE * errfile)8096 void qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile) {
8097 
8098   clock(); /* start the clock */
8099 #if qh_QHpointer
8100   if (!(qh_qh= (qhT *)malloc (sizeof(qhT)))) {
8101     fprintf (errfile, "qhull error (initqhull_globals): insufficient memory\n");
8102     exit (qh_ERRmem);  /* no error handler */
8103   }
8104   memset((char *)qh_qh, 0, sizeof(qhT));   /* every field is 0, FALSE, NULL */
8105 #else
8106   memset((char *)&qh_qh, 0, sizeof(qhT));
8107 #endif
8108   strcat (qh qhull, "qhull");
8109   qh_initstatistics();
8110   qh ferr= errfile;
8111   qh fin= infile;
8112   qh fout= outfile;
8113   qh lastreport= INT_MIN;
8114   qh mergereport= INT_MIN;
8115   qh max_outside= 0.0;
8116   qh maxmaxcoord= 0.0;
8117   qh max_vertex= 0.0;
8118   qh min_vertex= 0.0;
8119   qh MINdenom_1= fmax_(1.0/REALmax, REALmin);
8120   qh MINoutside= 0.0;
8121   qh MINvisible= REALmax;
8122   qh premerge_centrum= 0.0;
8123   qh premerge_cos= REALmax;
8124   qh PRINTprecision= True;
8125   qh PRINTradius= 0.0;
8126   qh postmerge_cos= REALmax;
8127   qh postmerge_centrum= 0.0;
8128   qh ROTATErandom= INT_MIN;
8129   qh DROPdim= -1;
8130   qh TRACEdist= REALmax;
8131   qh TRACEpoint= -1;
8132   qh tracefacet_id= (unsigned int) -1;  /* stderr set these to id for tracefacet/tracevertex */
8133   qh tracevertex_id= (unsigned int) -1;
8134 } /* initqhull_start */
8135 
8136 /*---------------------------------------------
8137 -initthresholds	set thresholds for printing and scaling from command line
8138   see 'prompt' in unix.c for documentation
8139   see also initflags()
8140   sets qh GOODthreshold or qh SPLITthreshold if 'Pd0D1' used
8141 */
qh_initthresholds(char * command)8142 void qh_initthresholds(char *command) {
8143   realT value;
8144   int index, maxdim, k;
8145   char *s= command;
8146   char key;
8147 
8148   maxdim= qh input_dim;
8149   if (qh DELAUNAY && (qh PROJECTdelaunay || qh PROJECTinput))
8150     maxdim++;
8151   while (*s) {
8152     if (*s == '-')
8153       s++;
8154     if (*s == 'P') {
8155       s++;
8156       while (*s && !isspace(key= *s++)) {
8157 	if (key == 'd' || key == 'D') {
8158 	  if (!isdigit(*s)) {
8159 	    fprintf(qh ferr, "qhull warning: no dimension given for Print option %c.  Ignored\n",
8160 		    key);
8161 	    continue;
8162 	  }
8163 	  index= qh_strtol (s, &s);
8164 	  if (index >= qh hull_dim) {
8165 	    fprintf(qh ferr, "qhull warning: dimension %d for Print option %c is >= %d.  Ignored\n",
8166 	        index, key, qh hull_dim);
8167 	    continue;
8168 	  }
8169 	  if (*s == ':') {
8170 	    ++s;
8171 	    value= qh_strtod(s, &s);
8172 	    if (fabs((double)value) > 1.0) {
8173 	      fprintf(qh ferr, "qhull warning: value %2.4g for Print option %c is > +1 or < -1.  Ignored\n",
8174 	              value, key);
8175 	      continue;
8176 	    }
8177 	  }else
8178 	    value= 0.0;
8179 	  if (key == 'd')
8180 	    qh lower_threshold[index]= value;
8181 	  else
8182 	    qh upper_threshold[index]= value;
8183 	}
8184       }
8185     }else if (*s == 'Q') {
8186       s++;
8187       while (*s && !isspace(key= *s++)) {
8188 	if (key == 'b' && *s == 'B') {
8189 	  s++;
8190 	  for (k=maxdim; k--; ) {
8191 	    qh lower_bound[k]= -qh_DEFAULTbox;
8192 	    qh upper_bound[k]= qh_DEFAULTbox;
8193 	  }
8194 	}else if (key == 'b' || key == 'B') {
8195 	  if (!isdigit(*s)) {
8196 	    fprintf(qh ferr, "qhull warning: no dimension given for Qhull option %c.  Ignored\n",
8197 		    key);
8198 	    continue;
8199 	  }
8200 	  index= qh_strtol (s, &s);
8201 	  if (index >= maxdim) {
8202 	    fprintf(qh ferr, "qhull warning: dimension %d for Qhull option %c is >= %d.  Ignored\n",
8203 	        index, key, maxdim);
8204 	    continue;
8205 	  }
8206 	  if (*s == ':') {
8207 	    ++s;
8208 	    value= qh_strtod(s, &s);
8209 	  }
8210 	  else if (key == 'b')
8211 	    value= -qh_DEFAULTbox;
8212 	  else
8213 	    value= qh_DEFAULTbox;
8214 	  if (key == 'b')
8215 	    qh lower_bound[index]= value;
8216 	  else
8217 	    qh upper_bound[index]= value;
8218 	}
8219       }
8220     }else {
8221       while (!isspace (*s))
8222         s++;
8223     }
8224     while (isspace (*s))
8225       s++;
8226   }
8227   for (k= qh hull_dim; k--; ) {
8228     if (qh lower_threshold[k] > -REALmax/2) {
8229       qh GOODthreshold= True;
8230       if (qh upper_threshold[k] < REALmax/2) {
8231         qh SPLITthresholds= True;
8232         qh GOODthreshold= False;
8233         break;
8234       }
8235     }else if (qh upper_threshold[k] < REALmax/2)
8236       qh GOODthreshold= True;
8237   }
8238 } /* initthresholds */
8239 
8240 #if qh_QHpointer
8241 /*------------------------------------------
8242 -restore_qhull- restores a previously saved qhull
8243   also restores qh_qhstat and qhmem.tempstack
8244   errors if current qhull hasn't been saved or freed
8245   uses qhmem for error reporting
8246 */
qh_restore_qhull(qhT ** oldqh)8247 void qh_restore_qhull (qhT **oldqh) {
8248 
8249   if (*oldqh && strcmp ((*oldqh)->qhull, "qhull")) qhull_fatal(77);
8250 
8251   if (qh_qh) qhull_fatal(78);
8252 
8253   if (!*oldqh || !(*oldqh)->old_qhstat) qhull_fatal(79);
8254 
8255   qh_qh= *oldqh;
8256   *oldqh= NULL;
8257   qh_qhstat= qh old_qhstat;
8258   qhmem.tempstack= qh old_tempstack;
8259   trace1((qh ferr, "qh_restore_qhull: restored qhull from %x\n", (int) *oldqh));
8260 } /* restore_qhull */
8261 
8262 /*------------------------------------------
8263 -save_qhull- saves qhull for a later qh_restore_qhull
8264   also saves qh_qhstat and qhmem.tempstack
8265 returns:
8266   qhull for a later restore_qhull
8267   qh_qh=NULL
8268 notes:
8269   need to initialize qhull or call qh_restore_qhull before continuing
8270 */
qh_save_qhull(void)8271 qhT *qh_save_qhull (void) {
8272   qhT *oldqh;
8273 
8274   if (!qh_qh) qhull_fatal(80);
8275 
8276   qh old_qhstat= qh_qhstat;
8277   qh_qhstat= NULL;
8278   qh old_tempstack= qhmem.tempstack;
8279   qhmem.tempstack= NULL;
8280   oldqh= qh_qh;
8281   qh_qh= NULL;
8282   trace1((qhmem.ferr, "qh_save_qhull: saved qhull %x\n", (int) oldqh));
8283   return oldqh;
8284 } /* save_qhull */
8285 
8286 #endif
8287 
8288 /*-----------------------------------------
8289 -strtol/tod -- internal versions that don't skip trailing spaces
8290 */
qh_strtod(const char * s,char ** endp)8291 double qh_strtod (const char *s, char **endp) {
8292   double result;
8293 
8294   result= strtod (s, endp);
8295   if (s < (*endp) && (*endp)[-1] == ' ')
8296     (*endp)--;
8297   return result;
8298 } /* strtod */
8299 
qh_strtol(const char * s,char ** endp)8300 int qh_strtol (const char *s, char **endp) {
8301   int result;
8302 
8303   result= (int) strtol (s, endp, 10);
8304   if (s< (*endp) && (*endp)[-1] == ' ')
8305     (*endp)--;
8306   return result;
8307 } /* strtol */
8308 
8309 
8310 
8311 /*************************************************************************/
8312 /****************** implementation code from qhull.c *********************/
8313 /*************************************************************************/
8314 
8315 /* qhull - Quickhull algorithm for convex hulls
8316 
8317    qhull() and top-level routines
8318 
8319    see README, qhull.h, unix.c and mac.c
8320 
8321    see qhull_a.h for internal functions
8322 
8323    copyright (c) 1993-1994 The Geometry Center
8324 */
8325 
8326 
8327 /*-------------------------------------------------
8328 -qhull- hull_dim convex hull of num_points starting at first_point
8329 returns:
8330   returns facet_list, numfacets, etc.
8331 */
qh_qhull(void)8332 void qh_qhull (void) {
8333   setT *maxpoints, *vertices;
8334   facetT *facet;
8335   int numpart, numoutside, i;
8336   vertexT *vertex;
8337   realT dist;
8338   boolT isoutside;
8339 
8340   qh hulltime= clock();
8341   if (qh DELAUNAY && qh upper_threshold[qh hull_dim-1] > REALmax/2
8342                   && qh lower_threshold[qh hull_dim-1] < -REALmax/2) {
8343     for (i= qh_PRINTEND; i--; ) {
8344       if (qh PRINTout[i] == qh_PRINTgeom && qh DROPdim < 0
8345  	  && !qh GOODthreshold && !qh SPLITthresholds)
8346 	break;  /* in this case, don't set upper_threshold */
8347     }
8348     if (i < 0) {
8349       qh upper_threshold[qh hull_dim-1]= 0.0;
8350       if (!qh GOODthreshold)
8351 	qh SPLITthresholds= True;
8352     }
8353   }
8354   maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim);
8355   /* qh_maxmin sets DISTround and other precision constants */
8356   vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points);
8357   qh_initialhull (vertices);  /* initial qh facet_list */
8358   qh_partitionall (vertices, qh first_point, qh num_points);
8359   if (qh PREmerge) {
8360     qh cos_max= qh premerge_cos;
8361     qh centrum_radius= qh premerge_centrum;
8362   }
8363   if (qh ONLYgood) {
8364 
8365     if (!(qh GOODthreshold || qh GOODpoint
8366 	  || (qh GOODvertex > 0 && !qh MERGING))) qhull_fatal(81);
8367 
8368     if (qh GOODvertex > 0  && !qh MERGING  /* matches qh_partitionall */
8369 	&& !qh_isvertex (qh GOODvertexp, vertices)) {
8370       facet= qh_findbest (qh GOODvertexp, qh facet_list, False, 0,
8371 			  &dist, &isoutside, &numpart);
8372       zadd_(Zdistgood, numpart);
8373 
8374       if (!isoutside) qhull_fatal(82);
8375 
8376       if (!qh_addpoint (qh GOODvertexp, facet, False)) {
8377 	qh_settempfree(&vertices);
8378 	qh_settempfree(&maxpoints);
8379 	return;
8380       }
8381     }
8382     qh_findgood (qh facet_list, 0);
8383   }
8384   qh_settempfree(&vertices);
8385   qh_settempfree(&maxpoints);
8386   qh_buildhull();
8387   if (qh POSTmerge && !qh STOPpoint && !qh STOPcone) {
8388     qh POSTmerging= True;
8389     qh cos_max= qh postmerge_cos;
8390     qh centrum_radius= qh postmerge_centrum;
8391     FORALLfacets
8392       zinc_(Zpostfacets);
8393     qh newfacet_list= qh facet_list;
8394     qh visible_list= qh facet_list;
8395     qh newfacet_id= 0;
8396     qh newvertex_list= qh vertex_list;
8397     FORALLvertices
8398       vertex->newlist= True;
8399     qh_vertexneighbors (/*qh facet_list*/);
8400     qh_merge_nonconvex(/*qh newfacet_list*/);
8401     qh_partitionvisible (/*visible_list, newfacet_list*/ (boolT)!qh_ALL, &numoutside);
8402     qh_deletevisible (/*qh visible_list*/);
8403     qh POSTmerging= False;
8404     qh cos_max= qh premerge_cos;
8405     qh centrum_radius= qh premerge_centrum;
8406   }
8407   if (!qh FORCEoutput && (qh MERGING || qh APPROXhull))
8408     qh_check_maxout ();
8409 
8410   if (qh_setsize ((setT *)qhmem.tempstack) != 0) qhull_fatal(83);
8411 
8412   qh hulltime= clock() - qh hulltime;
8413   qh QHULLfinished= True;
8414   trace1((qh ferr, "qh_qhull: algorithm completed\n"));
8415 } /* qhull */
8416 
8417 /*-------------------------------------------------
8418 -addpoint-  add point to hull above a facet
8419   if checkdist or !facet, locates a facet for the point
8420   if !checkdist and facet, assumes point is above facet (major damage if below)
8421 returns:
8422   if unknown point, adds it to qh other_points
8423   False if user requested break
8424 */
qh_addpoint(pointT * furthest,facetT * facet,boolT checkdist)8425 boolT qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist) {
8426   int goodvisible, goodhorizon;
8427   vertexT *vertex;
8428   facetT *newfacet;
8429   realT dist, newbalance, pbalance;
8430   boolT isoutside= False;
8431   int numpart, numpoints;
8432 
8433   if (qh_pointid (furthest) == -1)
8434     qh_setappend (&qh other_points, furthest);
8435   if (checkdist || !facet) {
8436     if (!facet)
8437       facet= qh facet_list;
8438     facet= qh_findbest (furthest, facet, False, 0, &dist, &isoutside, &numpart);
8439     zzadd_(Zpartition, numpart);
8440     if (!isoutside) {
8441       zinc_(Znotmax);  /* last point of outsideset is no longer furthest. */
8442       qh_partitioncoplanar (furthest, facet, &dist);
8443       return True;
8444     }
8445   }
8446   qh_buildtracing (furthest, facet);
8447   if (qh STOPpoint < 0 && qh furthest_id == -qh STOPpoint-1)
8448     return False;
8449   qh_findhorizon (furthest, facet, &goodvisible, &goodhorizon);
8450   if (qh ONLYgood && !(goodvisible+goodhorizon)) {
8451     zinc_(Znotgood);
8452     /* last point of outsideset is no longer furthest.  This is ok
8453        since all points of the outside are likely to be bad */
8454     qh_clearvisible (/*qh visible_list*/);
8455     return True;
8456   }
8457   zzinc_(Zprocessed);
8458   vertex= qh_makenewfacets (furthest /*visible_list, attaches if !ONLYgood */);
8459   newbalance= qh facet_id - qh newfacet_id;
8460   newbalance -= (realT) (qh num_facets-qh num_visible)*qh hull_dim/qh num_vertices;
8461   wadd_(Wnewbalance, newbalance);
8462   wadd_(Wnewbalance2, newbalance * newbalance);
8463   if (qh ONLYgood && !qh_findgood (qh newfacet_list, goodhorizon)) {
8464     FORALLnew_facets
8465       qh_delfacet (newfacet);
8466     qh_delvertex (vertex);
8467     qh_clearvisible (/*qh visible_list*/);
8468     qh_clearnewvertices (/* qh newvertex_list*/);
8469     zinc_(Znotgoodnew);
8470     return True;
8471   }
8472   qh_attachnewfacets(/*visible_list*/);
8473   qh_matchnewfacets();
8474   if (qh STOPcone && qh furthest_id == qh STOPcone-1)
8475     return False;
8476   if (qh PREmerge)
8477     qh_merge_nonconvex(/*qh newfacet_list*/);
8478   qh_partitionvisible (/*visible_list, newfacet_list*/ (boolT)!qh_ALL, &numpoints);
8479   zinc_(Zpbalance);
8480   pbalance= numpoints - (realT) qh hull_dim /* assumes all points extreme */
8481                 * (qh num_points - qh num_vertices)/qh num_vertices;
8482   wadd_(Wpbalance, pbalance);
8483   wadd_(Wpbalance2, pbalance * pbalance);
8484   qh_deletevisible (/*qh visible_list*/);
8485   qh_clearnewvertices (/* qh newvertex_list*/);
8486 
8487   /*
8488   if (qh IStracing >= 4)
8489     qh_printfacetlist (qh newfacet_list, NULL, True);
8490     NO LONGER IN SERVICE */
8491 
8492   if (qh CHECKfrequently) {
8493     if (qh num_facets < 50)
8494       qh_checkpolygon (qh facet_list);
8495     else
8496       qh_checkpolygon (qh newfacet_list);
8497   }
8498   if (qh STOPpoint > 0 && qh furthest_id == qh STOPpoint-1)
8499     return False;
8500   trace2((qh ferr, "qh_addpoint: added p%d new facets %d new balance %2.2g point balance %2.2g\n",
8501     qh_pointid (furthest), qh facet_id - qh newfacet_id, newbalance, pbalance));
8502   qh newfacet_id= qh facet_id;
8503   qh newfacet_list= NULL;
8504   return True;
8505 } /* addpoint */
8506 
8507 /*-------------------------------------------------
8508 -buildhull- constructs a hull by adding outside points one at a time
8509   may be called multiple times
8510   checks facet and vertex lists for 'visible' and 'newlist'
8511 notes:
8512   to recover from STOPcone, call qh_deletevisible and qh_clearnewvertices
8513 */
qh_buildhull(void)8514 void qh_buildhull(void) {
8515   facetT *facet;
8516   pointT *furthest;
8517   vertexT *vertex;
8518   int id;
8519 
8520   trace1((qh ferr, "qh_buildhull: start build hull\n"));
8521   FORALLfacets {
8522 
8523     if (facet->visible) qhull_fatal(84);
8524 
8525   }
8526   FORALLvertices {
8527 
8528     if (vertex->newlist) qhull_fatal(85);
8529 
8530     id= qh_pointid (vertex->point);
8531     if ((qh STOPpoint>0 && id == qh STOPpoint-1) ||
8532 	(qh STOPpoint<0 && id == -qh STOPpoint-1) ||
8533 	(qh STOPcone>0 && id == qh STOPcone-1)) {
8534       trace1((qh ferr,"qh_buildhull: stop point or cone P%d in initial hull\n", id));
8535       return;
8536     }
8537   }
8538   qh facet_next= qh facet_list;      /* advance facet when processed */
8539   while ((furthest= qh_nextfurthest (&facet))) {
8540     qh num_outside--;
8541     if (!qh_addpoint (furthest, facet, qh ONLYmax))
8542       break;
8543   }
8544   if (qh num_outside && !furthest) qhull_fatal(86);
8545 
8546   trace1((qh ferr, "qh_buildhull: completed the hull construction\n"));
8547 } /* buildhull */
8548 
8549 
8550 /*-------------------------------------------
8551 -buildtracing- for tracing execution of buildhull
8552   also resets visit_id, vertext_visit on wrap around
8553 */
qh_buildtracing(pointT * furthest,facetT * facet)8554 void qh_buildtracing (pointT *furthest, facetT *facet) {
8555   realT cpu, dist;
8556   time_t timedata;
8557   struct tm *tp;
8558   vertexT *vertex;
8559 
8560   qh furthest_id= qh_pointid(furthest);
8561   if (qh TRACEpoint == qh furthest_id) {
8562     qh IStracing= qh TRACElevel;
8563     qhmem.IStracing= qh TRACElevel;
8564   }
8565   if (qh REPORTfreq && (zzval_(Zsetplane) > qh lastreport+qh REPORTfreq)) {
8566     qh lastreport= zzval_(Zsetplane);
8567     time (&timedata);
8568     tp= localtime (&timedata);
8569     cpu= clock();
8570     cpu /= qh_SECticks;
8571     zinc_(Zdistio);
8572     qh_distplane (furthest, facet, &dist);
8573     fprintf (qh ferr, "\n\
8574 At %d:%d:%d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
8575  The current hull contains %d facets and %d vertices.  There are %d\n\
8576  outside points.  Next is point p%d (v%d), %2.2g above f%d.\n",
8577       tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, zzval_(Zsetplane),
8578       zzval_(Ztotmerge), qh num_facets, qh num_vertices, qh num_outside+1,
8579       qh furthest_id, qh vertex_id, dist, facet->id);
8580   }else if (qh IStracing >=1) {
8581     cpu= clock();
8582     cpu /= qh_SECticks;
8583     qh_distplane (furthest, facet, &dist);
8584     fprintf (qh ferr, "qh_buildhull: add p%d (v%d) to hull of %d facets (%2.2g above f%d) and %d outside.  %4.4g CPU secs.\n",
8585       qh furthest_id, qh vertex_id, qh num_facets, dist,
8586       facet->id, qh num_outside+1, cpu);
8587   }
8588 #ifndef __BCC55__
8589   // This condition is always false under BCC55
8590   if (qh visit_id > INT_MAX) {
8591     qh visit_id= 0;
8592     FORALLfacets
8593       facet->visitid= qh visit_id;
8594   }
8595 #endif  // __BCC55__
8596 #ifndef __BCC55__
8597   // This condition is always false under BCC55
8598   if (qh vertex_visit > INT_MAX) {
8599     qh vertex_visit= 0;
8600     FORALLvertices
8601       vertex->visitid= qh vertex_visit;
8602   }
8603 #endif  // __BCC55__
8604 } /* buildtracing */
8605 
8606 /*-------------------------------------------
8607 -errexit2- return exitcode to system after an error
8608   assumes exitcode non-zero
8609   for two facets, see qh_errexit() in user.c
8610 */
qh_errexit2(int exitcode,facetT * facet,facetT * otherfacet)8611 void qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet) {
8612   qhull_fatal(87);
8613 } /* errexit2 */
8614 
8615 
8616 /*-------------------------------------------------
8617 -findgood- identify good facets for qh ONLYgood
8618   GOODvertex>0 - facet includes point as vertex
8619     if !match, returns goodhorizon
8620     inactive if qh MERGING
8621   GOODpoint - facet is visible or coplanar (>0) or not visible (<0)
8622   GOODthreshold - facet->normal matches threshold
8623     if !goodhorizon and !match, selects facet with closest angle
8624        and sets GOODclosest
8625 returns:
8626   number of new, good facets found
8627   determins facet->good
8628   may update GOODclosest
8629 notes:
8630   findgood_all further reduces the good region
8631 */
qh_findgood(facetT * facetlist,int goodhorizon)8632 int qh_findgood (facetT *facetlist, int goodhorizon) {
8633   facetT *facet, *bestfacet;
8634   realT angle, bestangle, dist;
8635   int  numgood=0;
8636 
8637   if (qh GOODclosest) {
8638     bestfacet= qh GOODclosest;
8639     qh_inthresholds (bestfacet->normal, &bestangle);
8640   }else {
8641     bestfacet= NULL;
8642     bestangle= -REALmax;
8643   }
8644   FORALLfacet_(facetlist) {
8645     if (facet->good)
8646       numgood++;
8647   }
8648   if (qh GOODvertex>0 && !qh MERGING) {
8649     FORALLfacet_(facetlist) {
8650       if (!qh_isvertex (qh GOODvertexp, facet->vertices)) {
8651         facet->good= False;
8652         numgood--;
8653       }
8654     }
8655   }
8656   if (qh GOODpoint && numgood) {
8657     FORALLfacet_(facetlist) {
8658       if (facet->good) {
8659         zinc_(Zdistgood);
8660         qh_distplane (qh GOODpointp, facet, &dist);
8661         if ((qh GOODpoint > 0) ^ (dist > 0.0)) {
8662           facet->good= False;
8663           numgood--;
8664         }
8665       }
8666     }
8667   }
8668   if (qh GOODthreshold && (numgood || goodhorizon)) {
8669     FORALLfacet_(facetlist) {
8670       if (facet->good) {
8671         if (!qh_inthresholds (facet->normal, &angle)) {
8672           facet->good= False;
8673           numgood--;
8674           angle= fabs_(angle);
8675           if (angle > bestangle) {
8676             bestangle= angle;
8677             bestfacet= facet;
8678           }
8679         }
8680       }
8681     }
8682     if (!numgood && bestfacet && bestfacet != qh GOODclosest) {
8683       if (qh GOODclosest)
8684 	qh GOODclosest->good= False;
8685       qh GOODclosest= bestfacet;
8686       bestfacet->good= True;
8687       numgood++;
8688       trace2((qh ferr, "qh_findgood: f%d is closest (%2.2g) to thresholds\n",
8689            bestfacet->id, bestangle));
8690       return numgood;
8691     }else if (numgood && qh GOODclosest)
8692       qh GOODclosest->good= False;
8693   }
8694   zadd_(Zgoodfacet, numgood);
8695   trace2((qh ferr, "qh_findgood: found %d good facets\n", numgood));
8696   if (!numgood && qh GOODvertex>0 && !qh MERGING)
8697     return goodhorizon;
8698   return numgood;
8699 } /* findgood */
8700 
8701 /*-------------------------------------------------
8702 -findgood_all- apply other constraints for good facets (used by qh PRINTgood)
8703   GOODvertex - facet includes (>0) or doesn't include (<0) point as vertex
8704     if last good facet, prints warning and continues
8705   SPLITthreshold - facet->normal matches threshold, or if none, the closest one
8706   calls findgood if !ONLYgood
8707 returns:
8708   clears facet->good if not good
8709   sets qh num_good
8710 notes:
8711   this is like findgood but more restrictive
8712 */
qh_findgood_all(facetT * facetlist)8713 void qh_findgood_all (facetT *facetlist) {
8714   facetT *facet, *bestfacet=NULL;
8715   realT angle, bestangle= REALmax;
8716   int  numgood=0, startgood;
8717 
8718   if (!qh ONLYgood)
8719     qh_findgood (qh facet_list, 0);
8720   FORALLfacet_(facetlist) {
8721     if (facet->good)
8722       numgood++;
8723   }
8724   if (qh GOODvertex <0 || (qh GOODvertex > 0 && qh MERGING)) {
8725     FORALLfacet_(facetlist) {
8726       if ((qh GOODvertex > 0) ^ !!qh_isvertex (qh GOODvertexp, facet->vertices)) {
8727         if (!--numgood) {
8728           fprintf (qh ferr, "qhull warning: good vertex p%d does not match last good facet f%d.  Ignored.\n",
8729              qh_pointid(qh GOODvertexp), facet->id);
8730           return;
8731         }
8732         facet->good= False;
8733       }
8734     }
8735   }
8736   startgood= numgood;
8737   if (qh SPLITthresholds) {
8738     FORALLfacet_(facetlist) {
8739       if (facet->good) {
8740         if (!qh_inthresholds (facet->normal, &angle)) {
8741           facet->good= False;
8742           numgood--;
8743           angle= fabs_(angle);
8744           if (angle < bestangle) {
8745             bestangle= angle;
8746             bestfacet= facet;
8747           }
8748         }
8749       }
8750     }
8751     if (!numgood) {
8752       bestfacet->good= True;
8753       numgood++;
8754       trace0((qh ferr, "qh_findgood_all: f%d is closest (%2.2g) to thresholds\n",
8755            bestfacet->id, bestangle));
8756       return;
8757     }
8758   }
8759   qh num_good= numgood;
8760   trace0((qh ferr, "qh_findgood_all: %d good facets remain out of %d facets\n",
8761         numgood, startgood));
8762 } /* findgood_all */
8763 
8764 /*-------------------------------------------------
8765 -findhorizon- given a visible facet, find the point's horizon and visible facets
8766 returns:
8767   qh visible_list to all visible facets
8768     marks visible facets with ->visible
8769     goodvisible counts visible->good
8770     initializes num_visible
8771 notes:
8772   similar to delpoint()
8773 */
qh_findhorizon(pointT * point,facetT * facet,int * goodvisible,int * goodhorizon)8774 void qh_findhorizon(pointT *point, facetT *facet, int *goodvisible, int *goodhorizon) {
8775   facetT *neighbor, **neighborp, *visible;
8776   int numhorizon= 0;
8777   realT dist;
8778 #if qh_MAXoutside
8779   boolT ckminvis= (boolT)(qh MINvisible > qh DISTround), isoutside;
8780 #endif
8781 
8782   trace1((qh ferr,"qh_findhorizon: find horizon for point p%d facet f%d\n",qh_pointid(point),facet->id));
8783   *goodvisible= *goodhorizon= 0;
8784   zinc_(Ztotvisible);
8785   qh_removefacet(facet);  /* visible_list at end of qh facet_list */
8786   qh_appendfacet(facet);
8787   qh num_visible= 1;
8788   if (facet->good)
8789     (*goodvisible)++;
8790   qh visible_list= facet;
8791   facet->visible= True;
8792 
8793   /*
8794   if (qh IStracing >=4)
8795     qh_errprint ("visible", facet, NULL, NULL, NULL);
8796     NO LONGER IN SERVICE */
8797 
8798   qh visit_id++;
8799   FORALLvisible_facets {
8800     visible->visitid= qh visit_id;
8801     FOREACHneighbor_(visible) {
8802       if ((int)neighbor->visitid == qh visit_id)
8803         continue;
8804       neighbor->visitid= qh visit_id;
8805       zzinc_(Znumvisibility);
8806       qh_distplane(point, neighbor, &dist);
8807 #if qh_MAXoutside
8808       isoutside= False;
8809       if (ckminvis) {
8810         if (dist >= qh MINvisible)
8811           isoutside= True;
8812       }else if (qh ONLYmax) {  /* furthest points are at least maxoutside above */
8813         if (dist >= neighbor->maxoutside || dist >= qh max_vertex)
8814           isoutside= True;
8815       }else if (qh PREmerge) {
8816         if (dist >= qh MINoutside)
8817           isoutside= True;
8818       }else if (dist > qh DISTround)
8819         isoutside= True;
8820       if (isoutside) {
8821 #else
8822       if (dist > qh MINvisible) {
8823 #endif
8824         zinc_(Ztotvisible);
8825 	qh_removefacet(neighbor);  /* append to end of qh visible_list */
8826 	qh_appendfacet(neighbor);
8827 	neighbor->visible= True;
8828 	qh num_visible++;
8829 	if (neighbor->good)
8830 	  (*goodvisible)++;
8831 
8832 	/*
8833         if (qh IStracing >=4)
8834           qh_errprint ("visible", neighbor, NULL, NULL, NULL);
8835 	  NO LONGER IN SERVICE */
8836 
8837       }else {
8838     	if (dist > -qh DISTround) {
8839           zzinc_(Zcoplanarhorizon);
8840       	  trace0((qh ferr, "qh_findhorizon: point p%d is coplanar to horizon f%d, dist=%2.7g < qh MINvisible (%2.7g)\n",
8841 	      qh_pointid(point), neighbor->id, dist, qh MINvisible));
8842 	}
8843     	zinc_(Ztothorizon);
8844         numhorizon++;
8845 	if (neighbor->good)
8846 	  (*goodhorizon)++;
8847 
8848 	/*
8849         if (qh IStracing >=4)
8850           qh_errprint ("horizon", neighbor, NULL, NULL, NULL);
8851 	  NO LONGER IN SERVICE */
8852 
8853       }
8854     }
8855   }
8856 
8857   if (!numhorizon) qhull_fatal(88);
8858 
8859   trace1((qh ferr, "qh_findhorizon: %d horizon facets (good %d), %d visible (good %d) min visible %2.2g\n",
8860        numhorizon, *goodhorizon, qh num_visible, *goodvisible, qh MINvisible));
8861   if (qh IStracing >= 4 && qh num_facets < 50)
8862     qh_printlists ();
8863 } /* findhorizon */
8864 
8865 
8866 /*--------------------------------------------------
8867 -initialhull- constructs the initial hull as a qh hull_dim simplex of vertices
8868 */
8869 void qh_initialhull(setT *vertices) {
8870   facetT *facet, *firstfacet;
8871   int k;
8872   realT dist;
8873 
8874   qh_createsimplex(vertices);  /* qh facet_list */
8875   qh interior_point= qh_getcenter(vertices);
8876   firstfacet= qh facet_list;
8877   qh_setfacetplane(firstfacet);
8878   zinc_(Znumvisibility); /* needs to be in printsummary */
8879   qh_distplane(qh interior_point, firstfacet, &dist);
8880   if (dist > 0) {
8881     FORALLfacets
8882       facet->toporient ^= True;
8883   }
8884   FORALLfacets
8885     qh_setfacetplane(facet);
8886   FORALLfacets {
8887     if (!qh_checkflipped (facet, NULL, qh_ALL)) {/* due to axis-parallel facet */
8888       trace1((qh ferr, "qh_initialhull: initial orientation incorrect.  Correct all facets\n"));
8889       facet->flipped= False;
8890       FORALLfacets {
8891 	facet->toporient ^= True;
8892 	qh_orientoutside (facet);
8893       }
8894       break;
8895     }
8896   }
8897   FORALLfacets {
8898 
8899     if (!qh_checkflipped (facet, NULL, (boolT)!qh_ALL)) qhull_fatal(89);
8900 
8901   }
8902   zzval_(Zprocessed)= qh hull_dim+1;
8903   qh_checkpolygon (qh facet_list);
8904   qh_checkconvex(qh facet_list,   qh_DATAfault);
8905   if (qh IStracing >= 1) {
8906     fprintf(qh ferr, "qh_initialhull: simplex constructed, interior point:");
8907     for (k=0; k<qh hull_dim; k++)
8908       fprintf (qh ferr, " %6.4g", qh interior_point[k]);
8909     fprintf (qh ferr, "\n");
8910   }
8911   if (qh PREmerge)
8912     qh_vertexneighbors (/*qh facet_list*/);
8913 } /* initialhull */
8914 
8915 /*-------------------------------------------------
8916 -initialvertices- determines a non-singular set of initial vertices
8917   picks random points if qh RANDOMoutside && !ALLpoints
8918   all maxpoints are unique
8919 returns:
8920   temporary set of dim+1 vertices in descending order by vertex id
8921 notes:
8922   unless qh ALLpoints, uses maxpoints as long as determinate is non-zero
8923 */
8924 setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints) {
8925   pointT *point, **pointp;
8926   setT *vertices, *simplex;
8927   realT randr;
8928   int index, point_i, point_n;
8929 
8930   vertices= qh_settemp (dim + 1);
8931   simplex= qh_settemp (dim+1);
8932   if (qh ALLpoints)
8933     qh_maxsimplex (dim, NULL, points, numpoints, &simplex);
8934   else if (qh RANDOMoutside) {
8935     while (qh_setsize (simplex) != dim+1) {
8936       randr= qh_RANDOMint;
8937       randr= randr/(qh_RANDOMmax+1.0);
8938       index= (int)floor(qh num_points * randr);
8939       point= qh_point (index);
8940       qh_setunique (&simplex, point);
8941     }
8942   }else if (qh hull_dim >= 8) {
8943     qh_setunique (&simplex, SETfirst_(maxpoints));
8944     FOREACHpoint_i_(maxpoints) {
8945       if (point_i & 0x1) {     /* first pick up max/min x and max points */
8946         qh_setunique (&simplex, point);
8947         if (qh_setsize (simplex) == dim)  /* search for last point */
8948 	  break;
8949       }
8950     }
8951     if (qh_setsize (simplex) != dim) {
8952       while ((point= (pointT *)qh_setdellast (maxpoints))) {
8953         qh_setunique (&simplex, point);
8954         if (qh_setsize (simplex) == dim)
8955 	  break;
8956       }
8957     }
8958     index= 0;
8959     while (qh_setsize (simplex) != dim) {
8960       point= qh_point (index++);
8961       qh_setunique (&simplex, point);
8962     }
8963     qh_maxsimplex (dim, maxpoints, points, numpoints, &simplex);
8964   }else
8965     qh_maxsimplex (dim, maxpoints, points, numpoints, &simplex);
8966   FOREACHpoint_(simplex)
8967     qh_setaddnth (&vertices, 0, qh_newvertex(point)); /* descending order */
8968   qh_settempfree (&simplex);
8969   return vertices;
8970 } /* initialvertices */
8971 
8972 
8973 /*------------------------------------------------
8974 -nextfurthest- returns next furthest point for processing
8975 returns:
8976   NULL if none available
8977   visible facet for furthest
8978   removes empty outside sets
8979 */
8980 pointT *qh_nextfurthest (facetT **visible) {
8981   facetT *facet;
8982   int size; /* , index; UNUSED */
8983   /*  realT randr; UNUSED */
8984   pointT *furthest;
8985 
8986   while ((facet= qh facet_next) != qh facet_tail) {
8987     if (!facet->outsideset) {
8988       qh facet_next= facet->next;
8989       continue;
8990     }
8991     SETreturnsize_(facet->outsideset, size);
8992     if (!size) {
8993       qh_setfree (&facet->outsideset);
8994       qh facet_next= facet->next;
8995       continue;
8996     }
8997     if (!qh RANDOMoutside && !qh VIRTUALmemory) {
8998       *visible= facet;
8999       return (pointT *)(qh_setdellast (facet->outsideset));
9000     }
9001     if (qh RANDOMoutside) qhull_fatal(90);
9002 
9003     else { /* VIRTUALmemory */
9004       facet= qh facet_tail->previous;
9005       if (!(furthest= (pointT *)qh_setdellast(facet->outsideset))) {
9006         if (facet->outsideset)
9007           qh_setfree (&facet->outsideset);
9008         qh_removefacet (facet);
9009         qh_prependfacet (facet, &qh facet_list);
9010         continue;
9011       }
9012       *visible= facet;
9013       return furthest;
9014     }
9015   }
9016   return NULL;
9017 } /* nextfurthest */
9018 
9019 /*-------------------------------------------------
9020 -partitionall- partitions all points into the outsidesets of facets
9021    vertices= set of vertices used by qh facet_list
9022      does not partition qh GOODpoint
9023      if ONLYgood && !MERGING, does not partition GOODvertex
9024    qh newfacet_id=0 for qh_findbest
9025 notes:
9026    faster if qh facet_list sorted by anticipated size of outside set
9027 */
9028 void qh_partitionall(setT *vertices, pointT *points, int numpoints){
9029   setT *pointset;
9030   vertexT *vertex, **vertexp;
9031   pointT *point, **pointp, *bestpoint;
9032   int size, point_i, point_n, point_end, remaining, i, id;
9033   facetT *facet;
9034   realT bestdist= -REALmax, dist;
9035 
9036   trace1((qh ferr, "qh_partitionall: partition all points into outside sets\n"));
9037   pointset= qh_settemp (numpoints);
9038   pointp= SETaddr_(pointset, pointT);
9039   for (i=numpoints, point= points; i--; point += qh hull_dim)
9040     *(pointp++)= point;
9041   qh_settruncate (pointset, numpoints);
9042   FOREACHvertex_(vertices) {
9043     if ((id= qh_pointid(vertex->point)) >= 0)
9044       SETelem_(pointset, id)= NULL;
9045   }
9046   id= qh_pointid (qh GOODpointp);
9047   if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
9048     SETelem_(pointset, id)= NULL;
9049   if (qh GOODvertexp && qh ONLYgood && !qh MERGING) { /* matches qhull()*/
9050     if ((id= qh_pointid(qh GOODvertexp)) >= 0)
9051       SETelem_(pointset, id)= NULL;
9052   }
9053   if (!qh BESToutside) {
9054     zval_(Ztotpartition)= qh num_points - qh hull_dim - 1; /*misses GOOD... */
9055     remaining= qh num_facets;
9056     point_end= numpoints;
9057     FORALLfacets {
9058       size= point_end/(remaining--) + 100;
9059       facet->outsideset= qh_setnew (size);
9060       bestpoint= NULL;
9061       point_end= 0;
9062       FOREACHpoint_i_(pointset) {
9063         if (point) {
9064           zzinc_(Zpartitionall);
9065           qh_distplane (point, facet, &dist);
9066           if (dist < qh MINoutside)
9067             SETelem_(pointset, point_end++)= point;
9068           else {
9069 	    qh num_outside++;
9070             if (!bestpoint) {
9071               bestpoint= point;
9072               bestdist= dist;
9073             }else if (dist > bestdist) {
9074               qh_setappend (&facet->outsideset, bestpoint);
9075               bestpoint= point;
9076               bestdist= dist;
9077             }else
9078               qh_setappend (&facet->outsideset, point);
9079           }
9080         }
9081       }
9082       if (bestpoint) {
9083         qh_setappend (&facet->outsideset, bestpoint);
9084 #if !qh_COMPUTEfurthest
9085 	facet->furthestdist= bestdist;
9086 #endif
9087       }else
9088         qh_setfree (&facet->outsideset);
9089       qh_settruncate (pointset, point_end);
9090     }
9091   }
9092   FOREACHpoint_i_(pointset) {
9093     if (point)
9094       qh_partitionpoint(point, qh facet_list);
9095   }
9096   qh_settempfree(&pointset);
9097 
9098   /*
9099   if (qh IStracing >= 4)
9100     qh_printfacetlist (qh facet_list, NULL, True);
9101     NO LONGER IN SERVICE */
9102 
9103 } /* partitionall */
9104 
9105 
9106 /*-------------------------------------------------
9107 -partitioncoplanar- partition coplanar point to a facet
9108   if dist NULL, searches from bestfacet, and does nothing if inside
9109 returns:
9110   max_ouside, num_coplanar updated
9111   if KEEPcoplanar or KEEPinside
9112     point assigned to best coplanarset
9113 */
9114 void qh_partitioncoplanar (pointT *point, facetT *facet, realT *dist) {
9115   facetT *bestfacet;
9116   pointT *oldfurthest;
9117   realT bestdist, dist2;
9118   int numpart= 0;
9119   boolT isoutside;
9120 
9121   if (!dist) {
9122     bestfacet= qh_findbest (point, facet, True, 0, &bestdist, &isoutside, &numpart);
9123     zinc_(Ztotpartcoplanar);
9124     zzadd_(Zpartcoplanar, numpart);
9125     if (bestdist < qh min_vertex) {
9126       zinc_(Zcoplanarinside);
9127       if (!qh KEEPinside)
9128         return;
9129     }else
9130       qh num_coplanar++;
9131   }else {
9132     bestfacet= facet;
9133     bestdist= *dist;
9134     if (!qh KEEPinside || bestdist >= qh min_vertex)
9135       qh num_coplanar++;
9136   }
9137   if (qh KEEPcoplanar + qh KEEPinside) {
9138     oldfurthest= (pointT *)qh_setlast (bestfacet->coplanarset);
9139     if (oldfurthest) {
9140       zinc_(Zcomputefurthest);
9141       qh_distplane (oldfurthest, bestfacet, &dist2);
9142     }
9143     if (!oldfurthest || dist2 < bestdist) {
9144       qh_setappend(&bestfacet->coplanarset, point);
9145       maximize_(qh max_outside, bestdist);
9146     }else
9147       qh_setappend2ndlast(&bestfacet->coplanarset, point);
9148   }else
9149     maximize_(qh max_outside, bestdist);
9150   trace2((qh ferr, "qh_partitioncoplanar: point p%d is coplanar with facet f%d (or inside) dist %2.2g\n",
9151 	  qh_pointid(point), bestfacet->id, bestdist));
9152 } /* partitioncoplanar */
9153 
9154 
9155 /*-------------------------------------------------
9156 -partitionpoint- assigns point to a visible facet
9157     !BESToutside stops search when point is outside or new facets
9158     findbest does not search !newfacet_id if precise and !BESToutside
9159 */
9160 void qh_partitionpoint (pointT *point, facetT *facet) {
9161   realT bestdist;
9162   pointT *oldfurthest;
9163   boolT isoutside;
9164   facetT *bestfacet;
9165   int numpart;
9166 
9167   bestfacet= qh_findbest (point, facet, qh BESToutside, qh newfacet_id,
9168 			  &bestdist, &isoutside, &numpart);
9169   zinc_(Ztotpartition);
9170   zzadd_(Zpartition, numpart);
9171   if (isoutside) {
9172     if (!bestfacet->outsideset
9173     || !(oldfurthest= (pointT *)qh_setlast (bestfacet->outsideset))) {
9174       qh_setappend(&(bestfacet->outsideset), point);
9175       if (bestfacet->id < qh newfacet_id) {
9176         qh_removefacet (bestfacet);  /* move after qh facet_next */
9177         qh_appendfacet (bestfacet);
9178       }
9179     }else {
9180 #if qh_COMPUTEfurthest
9181       zinc_(Zcomputefurthest);
9182       qh_distplane (oldfurthest, bestfacet, &dist);
9183       if (dist < bestdist)
9184 	qh_setappend(&(bestfacet->outsideset), point);
9185       else
9186 	qh_setappend2ndlast(&(bestfacet->outsideset), point);
9187 #else
9188       if (bestfacet->furthestdist < bestdist) {
9189 	qh_setappend(&(bestfacet->outsideset), point);
9190 	bestfacet->furthestdist= bestdist;
9191       }else
9192 	qh_setappend2ndlast(&(bestfacet->outsideset), point);
9193 #endif
9194     }
9195     qh num_outside++;
9196     trace4((qh ferr, "qh_partitionpoint: point p%d is outside facet f%d\n",
9197 	  qh_pointid(point), bestfacet->id));
9198   }else if (bestdist < qh min_vertex) {
9199     zinc_(Zpartinside);
9200     trace4((qh ferr, "qh_partitionpoint: point p%d is inside all facets, closest to f%d dist %2.2g\n",
9201 	  qh_pointid(point), bestfacet->id, bestdist));
9202     if (qh KEEPinside)
9203       qh_partitioncoplanar (point, bestfacet, &bestdist);
9204   }else {
9205     zzinc_(Zcoplanarpart);
9206     if (qh KEEPcoplanar || bestdist > qh max_outside
9207 	|| (!qh BESToutside && qh newfacet_id && !qh MERGING))
9208       qh_partitioncoplanar (point, bestfacet, &bestdist);
9209   }
9210 } /* partitionpoint */
9211 
9212 /*-------------------------------------------------
9213 -partitionvisible- partitions points in visible_list to newfacet_list
9214   1st neighbor (if any) points to a horizon facet or a new facet
9215   repartitions coplanar points if allpoints
9216 */
9217 void qh_partitionvisible(/*visible_list*/ boolT allpoints, int *numoutside) {
9218   facetT *visible, *newfacet;
9219   pointT *point, **pointp;
9220   int coplanar=0, size;
9221   vertexT *vertex, **vertexp;
9222 
9223   if (qh ONLYmax)
9224     maximize_(qh MINoutside, qh max_vertex);
9225   *numoutside= 0;
9226   FORALLvisible_facets {
9227     if (!visible->outsideset && !visible->coplanarset)
9228       continue;
9229     newfacet= (facetT *)SETfirst_(visible->neighbors);
9230     while (newfacet && newfacet->visible)
9231       newfacet= (facetT *)SETfirst_(newfacet->neighbors);
9232     if (!newfacet)
9233       newfacet= qh newfacet_list;
9234     if (visible->outsideset) {
9235       size= qh_setsize (visible->outsideset);
9236       *numoutside += size;
9237       qh num_outside -= size;
9238       FOREACHpoint_(visible->outsideset)
9239         qh_partitionpoint (point, newfacet);
9240     }
9241     if (visible->coplanarset && (qh KEEPcoplanar || qh KEEPinside)) {
9242       size= qh_setsize (visible->coplanarset);
9243       coplanar += size;
9244       qh num_coplanar -= size;
9245       FOREACHpoint_(visible->coplanarset) {
9246         if (allpoints)
9247           qh_partitionpoint (point, newfacet);
9248         else
9249           qh_partitioncoplanar (point, newfacet, NULL);
9250       }
9251     }
9252   }
9253   FOREACHvertex_(qh del_vertices) {
9254     if (vertex->point) {
9255       if (qh DELAUNAY && !allpoints && !(qh APPROXhull | qh MERGING))
9256         fprintf (qh ferr, "qhull precision warning: point p%d (v%d) deleted due to roundoff errors\n",
9257            qh_pointid(vertex->point), vertex->id);
9258       if (allpoints)
9259         qh_partitionpoint (vertex->point, qh newfacet_list);
9260       else
9261         qh_partitioncoplanar (vertex->point, qh newfacet_list, NULL);
9262     }
9263   }
9264   trace1((qh ferr,"qh_partitionvisible: partitioned %d points from outsidesets and %d points from coplanarsets\n", *numoutside, coplanar));
9265 } /* partitionvisible */
9266 
9267 
9268