Added the qhull sources to the repository.
authorMichel Selten <michel@mselten.demon.nl>
Sat, 6 Dec 2003 19:17:13 +0000 (19:17 +0000)
committerMichel Selten <michel@mselten.demon.nl>
Sat, 6 Dec 2003 19:17:13 +0000 (19:17 +0000)
These files are needed by Solid.
I left out the generated Windows .exe files. If needed later on, I'll add
them.

48 files changed:
extern/qhull/COPYING.txt [new file with mode: 0755]
extern/qhull/README.txt [new file with mode: 0755]
extern/qhull/REGISTER.txt [new file with mode: 0755]
extern/qhull/VisualC6/qhull.dsw [new file with mode: 0755]
extern/qhull/VisualC6/qhull/qhull.dsp [new file with mode: 0755]
extern/qhull/include/qhull/geom.h [new file with mode: 0755]
extern/qhull/include/qhull/io.h [new file with mode: 0755]
extern/qhull/include/qhull/mem.h [new file with mode: 0755]
extern/qhull/include/qhull/merge.h [new file with mode: 0755]
extern/qhull/include/qhull/poly.h [new file with mode: 0755]
extern/qhull/include/qhull/qhull.h [new file with mode: 0755]
extern/qhull/include/qhull/qhull_a.h [new file with mode: 0755]
extern/qhull/include/qhull/qset.h [new file with mode: 0755]
extern/qhull/include/qhull/stat.h [new file with mode: 0755]
extern/qhull/include/qhull/user.h [new file with mode: 0755]
extern/qhull/src/Make-config.sh [new file with mode: 0755]
extern/qhull/src/Makefile.txt [new file with mode: 0755]
extern/qhull/src/geom.c [new file with mode: 0755]
extern/qhull/src/geom.h [new file with mode: 0755]
extern/qhull/src/geom2.c [new file with mode: 0755]
extern/qhull/src/global.c [new file with mode: 0755]
extern/qhull/src/io.c [new file with mode: 0755]
extern/qhull/src/io.h [new file with mode: 0755]
extern/qhull/src/mem.c [new file with mode: 0755]
extern/qhull/src/mem.h [new file with mode: 0755]
extern/qhull/src/merge.c [new file with mode: 0755]
extern/qhull/src/merge.h [new file with mode: 0755]
extern/qhull/src/poly.c [new file with mode: 0755]
extern/qhull/src/poly.h [new file with mode: 0755]
extern/qhull/src/poly2.c [new file with mode: 0755]
extern/qhull/src/qconvex.c [new file with mode: 0755]
extern/qhull/src/qdelaun.c [new file with mode: 0755]
extern/qhull/src/qhalf.c [new file with mode: 0755]
extern/qhull/src/qhull.c [new file with mode: 0755]
extern/qhull/src/qhull.h [new file with mode: 0755]
extern/qhull/src/qhull_a.h [new file with mode: 0755]
extern/qhull/src/qhull_interface.cpp [new file with mode: 0755]
extern/qhull/src/qset.c [new file with mode: 0755]
extern/qhull/src/qset.h [new file with mode: 0755]
extern/qhull/src/qvoronoi.c [new file with mode: 0755]
extern/qhull/src/rbox.c [new file with mode: 0755]
extern/qhull/src/stat.c [new file with mode: 0755]
extern/qhull/src/stat.h [new file with mode: 0755]
extern/qhull/src/unix.c [new file with mode: 0755]
extern/qhull/src/user.c [new file with mode: 0755]
extern/qhull/src/user.h [new file with mode: 0755]
extern/qhull/src/user_eg.c [new file with mode: 0755]
extern/qhull/src/user_eg2.c [new file with mode: 0755]

diff --git a/extern/qhull/COPYING.txt b/extern/qhull/COPYING.txt
new file mode 100755 (executable)
index 0000000..1334eba
--- /dev/null
@@ -0,0 +1,37 @@
+                    Qhull, Copyright (c) 1993-2002
+
+       The National Science and Technology Research Center for
+        Computation and Visualization of Geometric Structures
+                        (The Geometry Center)
+                       University of Minnesota
+                            400 Lind Hall
+                        207 Church Street S.E.
+                      Minneapolis, MN 55455  USA
+
+                       email: qhull@geom.umn.edu
+
+This software includes Qhull from The Geometry Center.  Qhull is 
+copyrighted as noted above.  Qhull is free software and may be obtained 
+via http from www.geom.umn.edu.  It may be freely copied, modified, 
+and redistributed under the following conditions:
+
+1. All copyright notices must remain intact in all files.
+
+2. A copy of this text file must be distributed along with any copies 
+   of Qhull that you redistribute; this includes copies that you have 
+   modified, or copies of programs or other software products that 
+   include Qhull.
+
+3. If you modify Qhull, you must include a notice giving the
+   name of the person performing the modification, the date of
+   modification, and the reason for such modification.
+
+4. When distributing modified versions of Qhull, or other software 
+   products that include Qhull, you must provide notice that the original 
+   source code may be obtained as noted above.
+
+5. There is no warranty or other guarantee of fitness for Qhull, it is 
+   provided solely "as is".  Bug reports or fixes may be sent to 
+   qhull_bug@geom.umn.edu; the authors may or may not act on them as 
+   they desire.
+
diff --git a/extern/qhull/README.txt b/extern/qhull/README.txt
new file mode 100755 (executable)
index 0000000..9ef958a
--- /dev/null
@@ -0,0 +1,318 @@
+Name
+
+      qhull, rbox         2002.1           August 20, 2002
+  
+Convex hull, Delaunay triangulation, Voronoi diagrams, Halfspace intersection
+      Documentation:
+        html/index.htm
+
+      Available from:
+        <http://www.geom.umn.edu/software/qhull>
+       <http://savannah.gnu.org/projects/qhull>
+       <http://www.thesa.com/software/qhull>
+
+      Version 1 (simplicial only):
+        <http://www.geom.umn.edu/software/qhull/qhull-1.0.tar.gz>
+        <http://www.geom.umn.edu/software/qhull/qhull.sit.hqx>
+       
+      News and a paper:
+        <http://www.geom.umn.edu/~bradb/qhull-news.html>
+        <http://www.geom.umn.edu/software/qhull/qhull-96.ps>
+
+Purpose
+
+  Qhull is a general dimension convex hull program that reads a set 
+  of points from stdin, and outputs the smallest convex set that contains 
+  the points to stdout.  It also generates Delaunay triangulations, Voronoi 
+  diagrams, furthest-site Voronoi diagrams, and halfspace intersections
+  about a point.  
+
+  Rbox is a useful tool in generating input for Qhull; it generates 
+  hypercubes, diamonds, cones, circles, simplices, spirals, 
+  lattices, and random points.
+  
+  Qhull produces graphical output for Geomview.  This helps with
+  understanding the output. <http://www.geomview.org>
+
+    
+Environment requirements
+
+  Qhull and rbox should run on all 32-bit and 64-bit computers.  Use
+  an ANSI C or C++ compiler to compile the program.  The software is 
+  self-contained.  
+  
+  Qhull is copyrighted software.  Please read COPYING.txt and REGISTER.txt
+  before using or distributing Qhull.
+
+To contribute to Qhull
+
+  Qhull is on Savannah, http://savannah.gnu.org/projects/qhull/
+
+Qhull on Windows 95, 98, ME, NT, 2000, XP
+
+  The zip file contains rbox.exe, qhull.exe, qconvex.exe, qdelaunay.exe, 
+  qhalf.exe, qvoronoi.exe, documentation files, and source files.
+  
+  To install Qhull:
+  - Unzip the files into a directory.  You may use WinZip32 <www.hotfiles.com>
+  - Open a DOS window for the directory.  
+  - In Windows 95, the DOS window needs improvement.
+      - Double-click on qhull\eg\qhull-go.bat to call doskey (arrow keys).
+      - Increase the size of the screen font to 8x12.
+      - If the text is too dim, fix the screen colors with shareware (e.g., crt.exe)
+  - If you use qhull a lot, consider using the Cygwin Unix shell,
+        Cygwin tools (http://sources.redhat.com/cygwin/)
+  - Execute 'qconvex' for a synopsis and examples.
+  - Execute 'rbox 10 | qconvex' to compute the convex hull of 10 random points.
+  - Execute 'rbox 10 | qconvex i TO file' to write results to 'file'. 
+  - If an error occurs, Windows 95 sends the error to stdout instead of stderr 
+      - use 'TO xxx' to send normal output to xxx and error output to stdout
+  - Browse the documentation: qhull\html\index.htm
+
+Compiling for Unix
+
+  The gzip file, qhull.tgz, contains documentation and source files for
+  qhull and rbox.  
+  
+  To unpack the gzip file
+  - tar zxf qhull.tgz
+  - cd qhull
+  
+  Compiling with the Debian Make:[R. Laboissiere]
+  - cd src
+  - ./Make-config.sh
+  - cd ..
+  - configure
+  - make
+
+  Compiling with Makefile (i.e., Makefile.txt)   
+  - cd src
+  - in Makefile, check the CC, CCOPTS1, PRINTMAN, and PRINTC defines
+      - the defaults are gcc and enscript
+      - CCOPTS1 should include the ANSI flag.  It defines __STDC__
+  - in user.h, check the definitions of qh_SECticks and qh_CPUclock.
+      - use '#define qh_CLOCKtype 2' for timing runs longer than 1 hour
+  - type: make 
+      - this builds: qhull qconvex qdelaunay qhalf qvoronoi rbox libqhull.a
+  - type: make doc
+      - this prints the man page
+      - See also qhull/html/index.htm
+  - if your compiler reports many errors, it is probably not a ANSI C compiler
+      - you will need to set the -ansi switch or find another compiler
+  - if your compiler warns about missing prototypes for fprintf() etc.
+      - this is ok, your compiler should have these in stdio.h
+  - if your compiler warns about missing prototypes for memset() etc.
+      - include memory.h in qhull_a.h
+  - if your compiler is gcc-2.95.1, you need to set flag -fno-strict-aliasing.  
+      - This flag is set by default for other versions [Karas, Krishnaswami]
+  - if your compiler reports "global.c: storage size of 'qh_qh' isn't known"
+      - delete the initializer "={0}" in global.c, stat.c and mem.c
+  - if your compiler warns about "stat.c: improper initializer"
+      - this is ok, the initializer is not used
+  - if you have trouble building libqhull.a with 'ar'
+      - try 'make -f Makefile.txt qhullx' 
+  - if the code compiles, the qhull test case will automatically execute
+  - if an error occurs, there's an incompatibility between machines
+      - For gcc-2.95.1, you need to set flag -fno-strict-aliasing.
+           It is set by default for other versions of gcc [Karas, Krishnaswami]
+      - If you can, try a different compiler 
+      - You can turn off the Qhull memory manager with qh_NOmem in mem.h
+      - You can turn off compiler optimization (-O2 in Makefile)
+      - If you find the source of the problem, please let us know
+  - if you have Geomview (www.geomview.org)
+       - try  'rbox 100 | qconvex G >a' and load 'a' into Geomview
+       - run 'q_eg' for Geomview examples of Qhull output (see qh-eg.htm)
+  - to install the programs and their man pages:
+      - define MANDIR and BINDIR
+      - type 'make install'
+
+Compiling for Windows NT, 2000, XP with cygwin (www.cygwin.com)
+
+    - install cygwin with gcc, make, ar, and ln
+    - cd qhull/src
+    - make -f Makefile.txt
+
+Compiling for Windows 95, 98, NT, 2000, XP
+
+  Qhull compiles as a console application in Visual C++ 5.0 at warning 
+  level 3.
+
+  Visual C++ quickstart for qhull.exe:  
+    - create a "Win32 console application" called "qhull"
+       - add the following files:
+           geom.c geom2.c global.c io.c mem.c merge.c poly.c poly2.c qhull.c
+               qset.c stat.c unix.c user.c
+    - create a "Win32 console application" called "rbox" 
+       - add rbox.c
+
+  Visual C++ quickstart for qhull library, qconvex.exe, etc.
+    - To simplify setting up lots of projects, 
+       - create a temporary "Win32 console application" called "source"
+       - add all .c files from .../src/...
+       - In Tools::Options::Tab
+         Set tab size to 8 and indent size to 2
+
+    - create a "Win32 console application" called "rbox"
+       - move rbox.c from "qhull source"
+       - for Project:Settings..., Link
+         you only need the default libraries
+       - build the project
+
+    - create a "Win32 static library" called "library"
+       - move these files from "qhull source"
+           geom.c geom2.c global.c io.c mem.c merge.c poly.c poly2.c qhull.c
+               qset.c stat.c user.c
+       - set the library file (use the same for debug and release)
+       - build the project
+
+    - create a "Win32 console application" called "qhull"
+       - move unix.c from "qhull source"
+       - Set the library file in Project:Settings..., Link
+       - Qhull does not use other libraries
+
+    - create a "Win32 console application" called "qconvex"
+       - move qconvex.c from "qhull source"
+       - Set the library file in Project:Settings..., Link
+
+    - do the same for qdelaun.c, qhalf, qvoronoi.c, user_eg.c, user_eg2.c
+       - delete "qhull sources" since it is no longer needed
+       - Set the library file in Project:Settings..., Link
+       - use Project:Settings to make any changes
+       - use batch build to rebuild everything
+  
+  Qhull compiles with Borland C++ 5.0 bcc32.  A Makefile is included.
+  Execute 'make -f MBorland'.  If you use the Borland IDE, set the ANSI
+  option in Options:Project:Compiler:Source:Language-compliance.
+  
+  Qhull compiles with Borland C++ 4.02 for Win32 and DOS Power Pack.  
+  Use 'make -f MBorland -D_DPMI'.  Qhull 1.0 compiles with Borland 
+  C++ 4.02.  For rbox 1.0, use "bcc32 -WX -w- -O2-e -erbox -lc rbox.c".  
+  Use the same options for Qhull 1.0. [D. Zwick]
+  
+  Qhull compiles with Metrowerks C++ 1.7 with the ANSI option.
+
+  If you turn on full warnings, the compiler will report a number of 
+  unused variables, variables set but not used, and dead code.  These are
+  intentional.  For example, variables may be initialized (unnecessarily)
+  to prevent warnings about possible use of uninitialized variables.  
+
+Compiling for the Power Macintosh
+
+  Qhull compiles for the Power Macintosh with Metrowerk's C compiler.
+  It uses the SIOUX interface to read point coordinates and return output.
+  There is no graphical output.  For project files, see 'Compiling for
+  Windows 95'.  Instead of using SIOUX, Qhull may be embedded within an 
+  application.  
+
+  Version 1 is available for Macintosh computers by download of qhull.sit.hqx
+  It reads point coordinates from a standard file and returns output
+  to a standard file.  There is no graphical output.
+
+
+Compiling for other machines
+  Some users have reported problems with compiling Qhull under Irix 5.1.  It
+  compiles under other versions of Irix. 
+  
+  If you have troubles with the memory manager, you can turn it off by
+  defining qh_NOmem in mem.h.
+
+  You may compile Qhull with a C++ compiler.  
+
+
+Distributed files
+
+  README.txt           // instructions for installing Qhull 
+  REGISTER.txt         // Qhull registration 
+  COPYING.txt          // copyright notice 
+  Announce.txt         // announcement 
+  Changes.txt          // change history for Qhull and rbox 
+  qh-faq.htm           // Frequently asked questions
+  qh-home.htm          // Home page 
+  qh-get.htm          // Download page
+  html/index.htm       // Manual
+  Makefile.txt         // Makefile for Unix or cygwin 'make' 
+  MBorland             // Makefile for Borland C++/Win32
+  Make-config.sh       // Create Debian configure and automake
+src/      
+  rbox consists of:
+     rbox.exe          // Win32 executable (.zip only) 
+     rbox.htm          // html manual 
+     rbox.man          // Unix man page 
+     rbox.txt
+     rbox.c            // source program 
+     
+  qhull consists of:
+     qhull.exe         // Win32 executables (.zip only) 
+     qconvex.exe
+     qdelaunay.exe
+     qhalf.exe
+     qvoronoi.exe
+     qhull-go.bat      // DOS window
+     qconvex.htm       // html manuals
+     qdelaun.htm
+     qdelau_f.htm        
+     qhalf.htm
+     qvoronoi.htm
+     qvoron_f.htm
+     qh-eg.htm
+     qh-impre.htm
+     qh-in.htm
+     index.htm
+     qh-opt*.htm
+     qh-quick.htm
+     qh--4d.gif,etc.   // images for manual 
+     qhull.man         // Unix man page 
+     qhull.txt
+     q_eg              // shell script for Geomview examples
+     q_egtest          // shell script for Geomview test examples
+     q_test            // shell script to test qhull
+  
+  top-level source files:
+     src/index.htm     // index to source files 
+        qh-...htm         //   specific files
+     user.h            // header file of user definable constants 
+     qhull.h           // header file for qhull 
+     unix.c            // Unix front end to qhull 
+     qhull.c           // Quickhull algorithm with partitioning 
+     user.c            // user re-definable functions 
+     user_eg.c         // example of incorporating qhull into a user program 
+     user_eg2.c        // more complex example 
+     qhull_interface.cpp // call Qhull from C++
+
+  other source files:
+     qhull_a.h         // include file for *.c 
+     geom.c            // geometric routines 
+     geom2.c
+     geom.h    
+     global.c          // global variables 
+     io.c              // input-output routines 
+     io.h
+     mem.c             // memory routines, this is stand-alone code 
+     mem.h
+     merge.c           // merging of non-convex facets 
+     merge.h
+     poly.c            // polyhedron routines 
+     poly2.c
+     poly.h 
+     qset.c            // set routines, this only depends on mem.c 
+     qset.h
+     stat.c            // statistics 
+     stat.h
+
+Authors:
+
+  C. Bradford Barber                    Hannu Huhdanpaa
+  bradb@geom.umn.edu                    hannu@geom.umn.edu
+  
+                    c/o The Geometry Center
+                    University of Minnesota
+                    400 Lind Hall
+                    207 Church Street S.E.
+                    Minneapolis, MN 55455
+  
+  This software was developed under NSF grants NSF/DMS-8920161 and
+  NSF-CCR-91-15793 750-7504 at the Geometry Center and Harvard 
+  University.  If you find Qhull useful, please let us know.
diff --git a/extern/qhull/REGISTER.txt b/extern/qhull/REGISTER.txt
new file mode 100755 (executable)
index 0000000..767eb1c
--- /dev/null
@@ -0,0 +1,37 @@
+Dear User of Geometry Center Software:
+
+We would like to find out how you are using our software.  Think of
+Geometry Center software as a new kind of shareware: you share your
+science and successes with us, and we share our software and support
+with you. 
+
+If you use Geometry Center software, please send us a note telling
+us what you are doing with it.
+
+We need to know:
+
+  (1) What you are working on - an abstract of your work would be
+      fine.
+
+  (2) What Geometry Center software you use.
+
+  (3) How that software has helped you, for example, by increasing
+      your productivity or allowing you to do things you could not do
+      before.  In particular, if you feel that Geometry Center
+      software has had a direct bearing on your work, please tell us
+      about this.
+
+We encourage you to cite the use of any Geometry Center software you
+have used in your publications.  
+
+To cite Qhull, use
+
+    Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The Quickhull 
+       algorithm for convex hulls," ACM Trans. on Mathematical Software,
+       Dec 1996.  http://www.geom.umn.edu/software/qhull
+
+Please send e-mail to
+
+    qhull@geom.umn.edu
+
+Thank you!
diff --git a/extern/qhull/VisualC6/qhull.dsw b/extern/qhull/VisualC6/qhull.dsw
new file mode 100755 (executable)
index 0000000..96c68d8
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "qhull"=".\qhull\qhull.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/extern/qhull/VisualC6/qhull/qhull.dsp b/extern/qhull/VisualC6/qhull/qhull.dsp
new file mode 100755 (executable)
index 0000000..83160b2
--- /dev/null
@@ -0,0 +1,180 @@
+# Microsoft Developer Studio Project File - Name="qhull" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=qhull - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "qhull.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "qhull.mak" CFG="qhull - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "qhull - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "qhull - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "qhull - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "qhull - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ  /c
+# ADD CPP /nologo /MD /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ  /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF 
+
+# Begin Target
+
+# Name "qhull - Win32 Release"
+# Name "qhull - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\src\geom.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\geom2.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\global.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\io.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\mem.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\merge.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\poly.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\poly2.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\qhull.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\qset.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\stat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\user.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\src\geom.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\io.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\mem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\merge.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\poly.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\qhull.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\qhull_a.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\qset.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\stat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\user.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/extern/qhull/include/qhull/geom.h b/extern/qhull/include/qhull/geom.h
new file mode 100755 (executable)
index 0000000..32440cf
--- /dev/null
@@ -0,0 +1,177 @@
+/*<html><pre>  -<a                             href="qh-geom.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+  geom.h 
+    header file for geometric routines
+
+   see qh-geom.htm and geom.c
+
+   copyright (c) 1993-2002 The Geometry Center        
+*/
+
+#ifndef qhDEFgeom
+#define qhDEFgeom 1
+
+/* ============ -macros- ======================== */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="fabs_">-</a>
+   
+  fabs_(a)
+    returns the absolute value of a
+*/
+#define fabs_( a ) ((( a ) < 0 ) ? -( a ):( a ))
+               
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="fmax_">-</a>
+  
+  fmax_(a,b)
+    returns the maximum value of a and b
+*/
+#define fmax_( a,b )  ( ( a ) < ( b ) ? ( b ) : ( a ) )
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="fmin_">-</a>
+
+  fmin_(a,b)
+    returns the minimum value of a and b
+*/
+#define fmin_( a,b )  ( ( a ) > ( b ) ? ( b ) : ( a ) )
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="maximize_">-</a>
+
+  maximize_(maxval, val)
+    set maxval to val if val is greater than maxval
+*/
+#define maximize_( maxval, val ) {if (( maxval ) < ( val )) ( maxval )= ( val );}
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="minimize_">-</a>
+
+  minimize_(minval, val)
+    set minval to val if val is less than minval
+*/
+#define minimize_( minval, val ) {if (( minval ) > ( val )) ( minval )= ( val );}
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="det2_">-</a>
+
+  det2_(a1, a2,     
+        b1, b2)
+  
+    compute a 2-d determinate
+*/
+#define det2_( a1,a2,b1,b2 ) (( a1 )*( b2 ) - ( a2 )*( b1 ))
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="det3_">-</a>
+  
+  det3_(a1, a2, a3,    
+       b1, b2, b3,
+       c1, c2, c3)
+  
+    compute a 3-d determinate
+*/
+#define det3_( a1,a2,a3,b1,b2,b3,c1,c2,c3 ) ( ( a1 )*det2_( b2,b3,c2,c3 ) \
+                - ( b1 )*det2_( a2,a3,c2,c3 ) + ( c1 )*det2_( a2,a3,b2,b3 ) )
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="dX">-</a>
+  
+  dX( p1, p2 )
+  dY( p1, p2 )
+  dZ( p1, p2 )
+  
+    given two indices into rows[],
+
+    compute the difference between X, Y, or Z coordinates
+*/
+#define dX( p1,p2 )  ( *( rows[p1] ) - *( rows[p2] ))
+#define dY( p1,p2 )  ( *( rows[p1]+1 ) - *( rows[p2]+1 ))
+#define dZ( p1,p2 )  ( *( rows[p1]+2 ) - *( rows[p2]+2 ))
+#define dW( p1,p2 )  ( *( rows[p1]+3 ) - *( rows[p2]+3 ))
+
+/*============= prototypes in alphabetical order, infrequent at end ======= */
+
+void    qh_backnormal (realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero);
+void   qh_distplane (pointT *point, facetT *facet, realT *dist);
+facetT *qh_findbest (pointT *point, facetT *startfacet,
+                    boolT bestoutside, boolT isnewfacets, boolT noupper,
+                    realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbesthorizon (boolT ischeckmax, pointT *point, 
+                    facetT *startfacet, boolT noupper, realT *bestdist, int *numpart);
+facetT *qh_findbestnew (pointT *point, facetT *startfacet, realT *dist, 
+                    boolT bestoutside, boolT *isoutside, int *numpart);
+void   qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero);
+realT   qh_getangle(pointT *vect1, pointT *vect2);
+pointT *qh_getcenter(setT *vertices);
+pointT *qh_getcentrum(facetT *facet);
+realT   qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist);
+void    qh_normalize (coordT *normal, int dim, boolT toporient);
+void    qh_normalize2 (coordT *normal, int dim, boolT toporient, 
+            realT *minnorm, boolT *ismin);
+pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist);
+
+void    qh_setfacetplane(facetT *newfacets);
+void   qh_sethyperplane_det (int dim, coordT **rows, coordT *point0, 
+              boolT toporient, coordT *normal, realT *offset, boolT *nearzero);
+void   qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0, 
+            boolT toporient, coordT *normal, coordT *offset, boolT *nearzero);
+boolT   qh_sharpnewfacets (void);
+
+/*========= infrequently used code in geom2.c =============*/
+
+
+coordT *qh_copypoints (coordT *points, int numpoints, int dimension);
+void    qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]);
+realT  qh_determinant (realT **rows, int dim, boolT *nearzero);
+realT   qh_detjoggle (pointT *points, int numpoints, int dimension);
+void    qh_detroundoff (void);
+realT   qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero);
+realT   qh_distnorm (int dim, pointT *point, pointT *normal, realT *offsetp);
+realT   qh_distround (int dimension, realT maxabs, realT maxsumabs);
+realT   qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv);
+realT   qh_facetarea (facetT *facet);
+realT   qh_facetarea_simplex (int dim, coordT *apex, setT *vertices, 
+          vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset);
+pointT *qh_facetcenter (setT *vertices);
+facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp, facetT **facetlist);
+void    qh_getarea (facetT *facetlist);
+boolT   qh_gram_schmidt(int dim, realT **rows);
+boolT   qh_inthresholds (coordT *normal, realT *angle);
+void    qh_joggleinput (void);
+realT  *qh_maxabsval (realT *normal, int dim);
+setT   *qh_maxmin(pointT *points, int numpoints, int dimension);
+realT   qh_maxouter (void);
+void    qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex);
+realT   qh_minabsval (realT *normal, int dim);
+int     qh_mindiff (realT *vecA, realT *vecB, int dim);
+boolT   qh_orientoutside (facetT *facet);
+void    qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
+coordT  qh_pointdist(pointT *point1, pointT *point2, int dim);
+void    qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol);
+void    qh_printpoints (FILE *fp, char *string, setT *points);
+void    qh_projectinput (void);
+void   qh_projectpoints (signed char *project, int n, realT *points, 
+             int numpoints, int dim, realT *newpoints, int newdim);
+int     qh_rand( void);
+void    qh_srand( int seed);
+realT   qh_randomfactor (void);
+void    qh_randommatrix (realT *buffer, int dim, realT **row);
+void    qh_rotateinput (realT **rows);
+void    qh_rotatepoints (realT *points, int numpoints, int dim, realT **rows);
+void    qh_scaleinput (void);
+void    qh_scalelast (coordT *points, int numpoints, int dim, coordT low,
+                  coordT high, coordT newhigh);
+void   qh_scalepoints (pointT *points, int numpoints, int dim,
+               realT *newlows, realT *newhighs);
+boolT   qh_sethalfspace (int dim, coordT *coords, coordT **nextp, 
+              coordT *normal, coordT *offset, coordT *feasible);
+coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
+pointT *qh_voronoi_center (int dim, setT *points);
+
+#endif /* qhDEFgeom */
+
+
+
diff --git a/extern/qhull/include/qhull/io.h b/extern/qhull/include/qhull/io.h
new file mode 100755 (executable)
index 0000000..351d56b
--- /dev/null
@@ -0,0 +1,149 @@
+/*<html><pre>  -<a                             href="qh-io.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   io.h 
+   declarations of Input/Output functions
+
+   see README, qhull.h and io.c
+
+   copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFio
+#define qhDEFio 1
+
+/*============ constants and flags ==================*/
+
+/*-<a                             href="qh-io.htm#TOC"
+  >--------------------------------</a><a name="qh_MAXfirst">-</a>
+  
+  qh_MAXfirst
+    maximum length of first two lines of stdin
+*/
+#define qh_MAXfirst  200
+
+/*-<a                             href="qh-io.htm#TOC"
+  >--------------------------------</a><a name="qh_MINradius">-</a>
+  
+  qh_MINradius
+    min radius for Gp and Gv, fraction of maxcoord
+*/
+#define qh_MINradius 0.02
+
+/*-<a                             href="qh-io.htm#TOC"
+  >--------------------------------</a><a name="qh_GEOMepsilon">-</a>
+  
+  qh_GEOMepsilon
+    adjust outer planes for 'lines closer' and geomview roundoff.  
+    This prevents bleed through.
+*/
+#define qh_GEOMepsilon 2e-3
+
+/*-<a                             href="qh-io.htm#TOC"
+  >--------------------------------</a><a name="qh_WHITESPACE">-</a>
+  
+  qh_WHITESPACE
+    possible values of white space
+*/
+#define qh_WHITESPACE " \n\t\v\r\f"
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >--------------------------------</a><a name="RIDGE">-</a>
+  
+  qh_RIDGE
+    to select which ridges to print in qh_eachvoronoi
+*/
+typedef enum
+{
+    qh_RIDGEall = 0, qh_RIDGEinner, qh_RIDGEouter
+}
+qh_RIDGE;
+
+/*-<a                             href="qh-io.htm#TOC"
+  >--------------------------------</a><a name="printvridgeT">-</a>
+  
+  printvridgeT
+    prints results of qh_printvdiagram
+
+  see:
+    <a href="io.c#printvridge">qh_printvridge</a> for an example
+*/
+typedef void (*printvridgeT)(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+
+/*============== -prototypes in alphabetical order =========*/
+
+void    dfacet( unsigned id);
+void    dvertex( unsigned id);
+void    qh_countfacets (facetT *facetlist, setT *facets, boolT printall, 
+              int *numfacetsp, int *numsimplicialp, int *totneighborsp, 
+              int *numridgesp, int *numcoplanarsp, int *numnumtricoplanarsp);
+pointT *qh_detvnorm (vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp);
+setT   *qh_detvridge (vertexT *vertex);
+setT   *qh_detvridge3 (vertexT *atvertex, vertexT *vertex);
+int     qh_eachvoronoi (FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder);
+int     qh_eachvoronoi_all (FILE *fp, printvridgeT printvridge, boolT isupper, qh_RIDGE innerouter, boolT inorder);
+void   qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist);
+setT   *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets);
+void    qh_geomplanes (facetT *facet, realT *outerplane, realT *innerplane);
+void    qh_markkeep (facetT *facetlist);
+setT   *qh_markvoronoi (facetT *facetlist, setT *facets, boolT printall, boolT *islowerp, int *numcentersp);
+void    qh_order_vertexneighbors(vertexT *vertex);
+void   qh_printafacet(FILE *fp, int format, facetT *facet, boolT printall);
+void    qh_printbegin (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void   qh_printcenter (FILE *fp, int format, char *string, facetT *facet);
+void    qh_printcentrum (FILE *fp, facetT *facet, realT radius);
+void    qh_printend (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printend4geom (FILE *fp, facetT *facet, int *num, boolT printall);
+void    qh_printextremes (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void    qh_printextremes_2d (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void    qh_printextremes_d (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void   qh_printfacet(FILE *fp, facetT *facet);
+void   qh_printfacet2math(FILE *fp, facetT *facet, int notfirst);
+void   qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]);
+void    qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
+                              facetT *facet, realT offset, realT color[3]);
+void   qh_printfacet3math (FILE *fp, facetT *facet, int notfirst);
+void   qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
+void   qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]);
+void   qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
+void   qh_printfacet3vertex(FILE *fp, facetT *facet, int format);
+void   qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
+void   qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
+void   qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, int format);
+void   qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, int format);
+void    qh_printfacetheader(FILE *fp, facetT *facet);
+void    qh_printfacetridges(FILE *fp, facetT *facet);
+void   qh_printfacets(FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void   qh_printhelp_degenerate(FILE *fp);
+void   qh_printhelp_singular(FILE *fp);
+void   qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
+                  setT *vertices, realT color[3]);
+void   qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall);
+void    qh_printline3geom (FILE *fp, pointT *pointA, pointT *pointB, realT color[3]);
+void   qh_printpoint(FILE *fp, char *string, pointT *point);
+void   qh_printpointid(FILE *fp, char *string, int dim, pointT *point, int id);
+void    qh_printpoint3 (FILE *fp, pointT *point);
+void    qh_printpoints_out (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void    qh_printpointvect (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]);
+void    qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius);
+void   qh_printridge(FILE *fp, ridgeT *ridge);
+void    qh_printspheres(FILE *fp, setT *vertices, realT radius);
+void    qh_printvdiagram (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+int     qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder);
+void   qh_printvertex(FILE *fp, vertexT *vertex);
+void   qh_printvertexlist (FILE *fp, char* string, facetT *facetlist,
+                         setT *facets, boolT printall);
+void   qh_printvertices (FILE *fp, char* string, setT *vertices);
+void    qh_printvneighbors (FILE *fp, facetT* facetlist, setT *facets, boolT printall);
+void    qh_printvoronoi (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printvnorm (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+void    qh_printvridge (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+void   qh_produce_output(void);
+void    qh_projectdim3 (pointT *source, pointT *destination);
+int     qh_readfeasible (int dim, char *remainder);
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
+void    qh_setfeasible (int dim);
+boolT  qh_skipfacet(facetT *facet);
+
+#endif /* qhDEFio */
diff --git a/extern/qhull/include/qhull/mem.h b/extern/qhull/include/qhull/mem.h
new file mode 100755 (executable)
index 0000000..e9ebd1b
--- /dev/null
@@ -0,0 +1,174 @@
+/*<html><pre>  -<a                             href="qh-mem.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   mem.h 
+     prototypes for memory management functions
+
+   see qh-mem.htm, mem.c and qset.h
+
+   for error handling, writes message and calls
+     qh_errexit (qhmem_ERRmem, NULL, NULL) if insufficient memory
+       and
+     qh_errexit (qhmem_ERRqhull, NULL, NULL) otherwise
+
+   copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFmem
+#define qhDEFmem
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >-------------------------------</a><a name="NOmem">-</a>
+  
+  qh_NOmem
+    turn off quick-fit memory allocation
+
+  notes:
+    mem.c implements Quickfit memory allocation for about 20% time
+    savings.  If it fails on your machine, try to locate the
+    problem, and send the answer to qhull@geom.umn.edu.  If this can
+    not be done, define qh_NOmem to use malloc/free instead.
+
+   #define qh_NOmem
+*/
+
+/*-------------------------------------------
+    to avoid bus errors, memory allocation must consider alignment requirements.
+    malloc() automatically takes care of alignment.   Since mem.c manages
+    its own memory, we need to explicitly specify alignment in
+    qh_meminitbuffers().
+
+    A safe choice is sizeof(double).  sizeof(float) may be used if doubles 
+    do not occur in data structures and pointers are the same size.  Be careful
+    of machines (e.g., DEC Alpha) with large pointers.  If gcc is available, 
+    use __alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)).
+
+   see <a href="user.h#MEMalign">qh_MEMalign</a> in user.h for qhull's alignment
+*/
+
+#define qhmem_ERRmem 4    /* matches qh_ERRmem in qhull.h */
+#define qhmem_ERRqhull 5  /* matches qh_ERRqhull in qhull.h */
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >--------------------------------</a><a name="ptr_intT">-</a>
+  
+  ptr_intT
+    for casting a void* to an integer-type
+  
+  notes:
+    On 64-bit machines, a pointer may be larger than an 'int'.  
+    qh_meminit() checks that 'long' holds a 'void*'
+*/
+typedef unsigned long ptr_intT;
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >--------------------------------</a><a name="qhmemT">-</a>
+  qhmemT
+    global memory structure for mem.c
+ notes:
+   users should ignore qhmem except for writing extensions
+   qhmem is allocated in mem.c 
+   
+   qhmem could be swapable like qh and qhstat, but then
+   multiple qh's and qhmem's would need to keep in synch.  
+   A swapable qhmem would also waste memory buffers.  As long
+   as memory operations are atomic, there is no problem with
+   multiple qh structures being active at the same time.
+   If you need separate address spaces, you can swap the
+   contents of qhmem.
+*/
+typedef struct qhmemT qhmemT;
+extern qhmemT qhmem; 
+
+struct qhmemT {               /* global memory management variables */
+  int      BUFsize;          /* size of memory allocation buffer */
+  int      BUFinit;          /* initial size of memory allocation buffer */
+  int      TABLEsize;         /* actual number of sizes in free list table */
+  int      NUMsizes;          /* maximum number of sizes in free list table */
+  int      LASTsize;          /* last size in free list table */
+  int      ALIGNmask;         /* worst-case alignment, must be 2^n-1 */
+  void  **freelists;          /* free list table, linked by offset 0 */
+  int     *sizetable;         /* size of each freelist */
+  int     *indextable;        /* size->index table */
+  void    *curbuffer;         /* current buffer, linked by offset 0 */
+  void    *freemem;           /*   free memory in curbuffer */
+  int     freesize;          /*   size of free memory in bytes */
+  void           *tempstack;         /* stack of temporary memory, managed by users */
+  FILE    *ferr;              /* file for reporting errors */
+  int      IStracing;         /* =5 if tracing memory allocations */
+  int      cntquick;          /* count of quick allocations */
+                              /* remove statistics doesn't effect speed */
+  int      cntshort;          /* count of short allocations */
+  int      cntlong;           /* count of long allocations */
+  int      curlong;           /* current count of inuse, long allocations */
+  int      freeshort;        /* count of short memfrees */
+  int      freelong;         /* count of long memfrees */
+  int      totshort;          /* total size of short allocations */
+  int      totlong;           /* total size of long allocations */
+  int      maxlong;           /* maximum totlong */
+  int      cntlarger;         /* count of setlarger's */
+  int      totlarger;         /* total copied by setlarger */
+};
+
+
+/*==================== -macros ====================*/
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >--------------------------------</a><a name="memalloc_">-</a>
+   
+  qh_memalloc_(size, object, type)  
+    returns object of size bytes 
+       assumes size<=qhmem.LASTsize and void **freelistp is a temp
+*/
+
+#ifdef qh_NOmem
+#define qh_memalloc_(size, freelistp, object, type) {\
+  object= (type*)qh_memalloc (size); }
+#else /* !qh_NOmem */
+
+#define qh_memalloc_(size, freelistp, object, type) {\
+  freelistp= qhmem.freelists + qhmem.indextable[size];\
+  if ((object= (type*)*freelistp)) {\
+    qhmem.cntquick++;  \
+    *freelistp= *((void **)*freelistp);\
+  }else object= (type*)qh_memalloc (size);}
+#endif
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >--------------------------------</a><a name="memfree_">-</a>
+   
+  qh_memfree_(object, size) 
+    free up an object
+
+  notes:
+    object may be NULL
+    assumes size<=qhmem.LASTsize and void **freelistp is a temp
+*/
+#ifdef qh_NOmem
+#define qh_memfree_(object, size, freelistp) {\
+  qh_memfree (object, size); }
+#else /* !qh_NOmem */
+
+#define qh_memfree_(object, size, freelistp) {\
+  if (object) { \
+    qhmem .freeshort++;\
+    freelistp= qhmem.freelists + qhmem.indextable[size];\
+    *((void **)object)= *freelistp;\
+    *freelistp= object;}}
+#endif
+
+/*=============== prototypes in alphabetical order ============*/
+
+void *qh_memalloc(int insize);
+void qh_memfree (void *object, int size);
+void qh_memfreeshort (int *curlong, int *totlong);
+void qh_meminit (FILE *ferr);
+void qh_meminitbuffers (int tracelevel, int alignment, int numsizes,
+                       int bufsize, int bufinit);
+void qh_memsetup (void);
+void qh_memsize(int size);
+void qh_memstatistics (FILE *fp);
+
+#endif /* qhDEFmem */
diff --git a/extern/qhull/include/qhull/merge.h b/extern/qhull/include/qhull/merge.h
new file mode 100755 (executable)
index 0000000..7fc2afa
--- /dev/null
@@ -0,0 +1,171 @@
+/*<html><pre>  -<a                             href="qh-merge.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   merge.h 
+   header file for merge.c
+
+   see qh-merge.htm and merge.c
+
+   copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFmerge
+#define qhDEFmerge 1
+
+
+/*============ -constants- ==============*/
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="qh_ANGLEredundant">-</a>
+
+  qh_ANGLEredundant
+    indicates redundant merge in mergeT->angle
+*/
+#define qh_ANGLEredundant 6.0
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="qh_ANGLEdegen">-</a>
+  
+  qh_ANGLEdegen
+    indicates degenerate facet in mergeT->angle
+*/
+#define qh_ANGLEdegen     5.0
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="qh_ANGLEconcave">-</a>
+  
+  qh_ANGLEconcave
+    offset to indicate concave facets in mergeT->angle
+  
+  notes:
+    concave facets are assigned the range of [2,4] in mergeT->angle
+    roundoff error may make the angle less than 2
+*/
+#define qh_ANGLEconcave  1.5
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="MRG">-</a>
+  
+  MRG... (mergeType)
+    indicates the type of a merge (mergeT->type)
+*/
+typedef enum { /* in sort order for facet_mergeset */
+  MRGnone= 0,
+  MRGcoplanar,         /* centrum coplanar */
+  MRGanglecoplanar,    /* angle coplanar */
+                       /* could detect half concave ridges */
+  MRGconcave,          /* concave ridge */
+  MRGflip,             /* flipped facet. facet1 == facet2 */
+  MRGridge,            /* duplicate ridge (qh_MERGEridge) */
+                        /* degen and redundant go onto degen_mergeset */
+  MRGdegen,            /* degenerate facet (not enough neighbors) facet1 == facet2 */
+  MRGredundant,                /* redundant facet (vertex subset) */
+                       /* merge_degenredundant assumes degen < redundant */
+  MRGmirror,           /* mirror facet from qh_triangulate */
+  ENDmrg
+} mergeType;
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="qh_MERGEapex">-</a>
+  
+  qh_MERGEapex
+    flag for qh_mergefacet() to indicate an apex merge  
+*/
+#define qh_MERGEapex     True
+
+/*============ -structures- ====================*/
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="mergeT">-</a>
+     
+  mergeT
+    structure used to merge facets
+*/
+
+typedef struct mergeT mergeT;
+struct mergeT {                /* initialize in qh_appendmergeset */
+  realT   angle;        /* angle between normals of facet1 and facet2 */
+  facetT *facet1;      /* will merge facet1 into facet2 */
+  facetT *facet2;
+  mergeType type;
+};
+
+
+/*=========== -macros- =========================*/
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="FOREACHmerge_">-</a>
+     
+  FOREACHmerge_( merges ) {...}
+    assign 'merge' to each merge in merges
+       
+  notes:
+    uses 'mergeT *merge, **mergep;'
+    if qh_mergefacet(),
+      restart since qh.facet_mergeset may change
+    see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHmerge_( merges ) FOREACHsetelement_(mergeT, merges, merge)
+
+/*============ prototypes in alphabetical order after pre/postmerge =======*/
+
+void    qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle);
+void    qh_postmerge (char *reason, realT maxcentrum, realT maxangle, 
+             boolT vneighbors);
+void    qh_all_merges (boolT othermerge, boolT vneighbors);
+void    qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle);
+setT   *qh_basevertices( facetT *samecycle);
+void    qh_checkconnect (void /* qh new_facets */);
+boolT   qh_checkzero (boolT testall);
+void    qh_copynonconvex (ridgeT *atridge);
+void    qh_degen_redundant_facet (facetT *facet);
+void           qh_degen_redundant_neighbors (facetT *facet, facetT *delfacet);
+vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges);
+void    qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor,
+           facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp);
+facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp);
+void   qh_flippedmerges(facetT *facetlist, boolT *wasmerge);
+void   qh_forcedmerges( boolT *wasmerge);
+void   qh_getmergeset(facetT *facetlist);
+void   qh_getmergeset_initial (facetT *facetlist);
+void    qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex);
+ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge, 
+              vertexT *vertex, vertexT *oldvertex, int *hashslot);
+void   qh_makeridges(facetT *facet);
+void    qh_mark_dupridges(facetT *facetlist);
+void    qh_maydropneighbor (facetT *facet);
+int     qh_merge_degenredundant (void);
+void    qh_merge_nonconvex( facetT *facet1, facetT *facet2, mergeType mergetype);
+void    qh_mergecycle (facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_all (facetT *facetlist, boolT *wasmerge);
+void    qh_mergecycle_facets( facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_vneighbors( facetT *samecycle, facetT *newfacet);
+void   qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex);
+void    qh_mergefacet2d (facetT *facet1, facetT *facet2);
+void   qh_mergeneighbors(facetT *facet1, facetT *facet2);
+void   qh_mergeridges(facetT *facet1, facetT *facet2);
+void    qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex);
+void    qh_mergevertex_del (vertexT *vertex, facetT *facet1, facetT *facet2);
+void    qh_mergevertex_neighbors(facetT *facet1, facetT *facet2);
+void   qh_mergevertices(setT *vertices1, setT **vertices);
+setT   *qh_neighbor_intersections (vertexT *vertex);
+void    qh_newvertices (setT *vertices);
+boolT   qh_reducevertices (void);
+vertexT *qh_redundant_vertex (vertexT *vertex);
+boolT   qh_remove_extravertices (facetT *facet);
+vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet);
+void   qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex);
+void    qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges,
+                       facetT *oldfacet, facetT *neighborA);
+boolT  qh_test_appendmerge (facetT *facet, facetT *neighbor);
+boolT   qh_test_vneighbors (void /* qh newfacet_list */);
+void    qh_tracemerge (facetT *facet1, facetT *facet2);
+void    qh_tracemerging (void);
+void    qh_updatetested( facetT *facet1, facetT *facet2);
+setT   *qh_vertexridges (vertexT *vertex);
+void    qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges);
+void    qh_willdelete (facetT *facet, facetT *replace);
+
+#endif /* qhDEFmerge */
diff --git a/extern/qhull/include/qhull/poly.h b/extern/qhull/include/qhull/poly.h
new file mode 100755 (executable)
index 0000000..294ec95
--- /dev/null
@@ -0,0 +1,290 @@
+/*<html><pre>  -<a                             href="qh-poly.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   poly.h 
+   header file for poly.c and poly2.c
+
+   see qh-poly.htm, qhull.h and poly.c
+
+   copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFpoly
+#define qhDEFpoly 1
+
+/*===============   constants ========================== */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="ALGORITHMfault">-</a>
+  
+  ALGORITHMfault   
+    use as argument to checkconvex() to report errors during buildhull
+*/
+#define qh_ALGORITHMfault 0
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="DATAfault">-</a>
+  
+  DATAfault        
+    use as argument to checkconvex() to report errors during initialhull
+*/
+#define qh_DATAfault 1
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="DUPLICATEridge">-</a>
+  
+  DUPLICATEridge
+    special value for facet->neighbor to indicate a duplicate ridge
+  
+  notes:
+    set by matchneighbor, used by matchmatch and mark_dupridge
+*/
+#define qh_DUPLICATEridge ( facetT * ) 1L
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="MERGEridge">-</a>
+  
+  MERGEridge       flag in facet
+    special value for facet->neighbor to indicate a merged ridge
+  
+  notes:
+    set by matchneighbor, used by matchmatch and mark_dupridge
+*/
+#define qh_MERGEridge ( facetT * ) 2L
+
+
+/*============ -structures- ====================*/
+
+/*=========== -macros- =========================*/
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLfacet_">-</a>
+  
+  FORALLfacet_( facetlist ) { ... }
+    assign 'facet' to each facet in facetlist
+    
+  notes:
+    uses 'facetT *facet;'
+    assumes last facet is a sentinel
+    
+  see:
+    FORALLfacets
+*/
+#define FORALLfacet_( facetlist ) if ( facetlist ) for( facet=( facetlist );facet && facet->next;facet=facet->next )
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLnew_facets">-</a>
+  
+  FORALLnew_facets { ... } 
+    assign 'newfacet' to each facet in qh.newfacet_list
+    
+  notes:
+    uses 'facetT *newfacet;'
+    at exit, newfacet==NULL
+*/
+#define FORALLnew_facets for( newfacet=qh newfacet_list;newfacet && newfacet->next;newfacet=newfacet->next )
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLvertex_">-</a>
+  
+  FORALLvertex_( vertexlist ) { ... }
+    assign 'vertex' to each vertex in vertexlist
+    
+  notes:
+    uses 'vertexT *vertex;'
+    at exit, vertex==NULL
+*/
+#define FORALLvertex_( vertexlist ) for ( vertex=( vertexlist );vertex && vertex->next;vertex= vertex->next )
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLvisible_facets">-</a>
+  
+  FORALLvisible_facets { ... }
+    assign 'visible' to each visible facet in qh.visible_list
+    
+  notes:
+    uses 'vacetT *visible;'
+    at exit, visible==NULL
+*/
+#define FORALLvisible_facets for (visible=qh visible_list; visible && visible->visible; visible= visible->next)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLsame_">-</a>
+  
+  FORALLsame_( newfacet ) { ... } 
+    assign 'same' to each facet in newfacet->f.samecycle
+    
+  notes:
+    uses 'facetT *same;'
+    stops when it returns to newfacet
+*/
+#define FORALLsame_(newfacet) for (same= newfacet->f.samecycle; same != newfacet; same= same->f.samecycle)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLsame_cycle_">-</a>
+  
+  FORALLsame_cycle_( newfacet ) { ... } 
+    assign 'same' to each facet in newfacet->f.samecycle
+    
+  notes:
+    uses 'facetT *same;'
+    at exit, same == NULL
+*/
+#define FORALLsame_cycle_(newfacet) \
+     for (same= newfacet->f.samecycle; \
+         same; same= (same == newfacet ?  NULL : same->f.samecycle))
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHneighborA_">-</a>
+  
+  FOREACHneighborA_( facet ) { ... }
+    assign 'neighborA' to each neighbor in facet->neighbors
+  
+  FOREACHneighborA_( vertex ) { ... }
+    assign 'neighborA' to each neighbor in vertex->neighbors
+  
+  declare:
+    facetT *neighborA, **neighborAp;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHneighborA_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighborA)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHvisible_">-</a>
+  
+  FOREACHvisible_( facets ) { ... } 
+    assign 'visible' to each facet in facets
+    
+  notes:
+    uses 'facetT *facet, *facetp;'
+    see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHnewfacet_">-</a>
+  
+  FOREACHnewfacet_( facets ) { ... } 
+    assign 'newfacet' to each facet in facets
+    
+  notes:
+    uses 'facetT *newfacet, *newfacetp;'
+    see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHvertexA_">-</a>
+  
+  FOREACHvertexA_( vertices ) { ... } 
+    assign 'vertexA' to each vertex in vertices
+    
+  notes:
+    uses 'vertexT *vertexA, *vertexAp;'
+    see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHvertexreverse12_">-</a>
+  
+  FOREACHvertexreverse12_( vertices ) { ... } 
+    assign 'vertex' to each vertex in vertices
+    reverse order of first two vertices
+    
+  notes:
+    uses 'vertexT *vertex, *vertexp;'
+    see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)
+
+
+/*=============== prototypes poly.c in alphabetical order ================*/
+
+void    qh_appendfacet(facetT *facet);
+void    qh_appendvertex(vertexT *vertex);
+void   qh_attachnewfacets (void);
+boolT   qh_checkflipped (facetT *facet, realT *dist, boolT allerror);
+void   qh_delfacet(facetT *facet);
+void   qh_deletevisible(void /*qh visible_list, qh horizon_list*/);
+setT   *qh_facetintersect (facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra);
+unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem);
+facetT *qh_makenewfacet(setT *vertices, boolT toporient, facetT *facet);
+void    qh_makenewplanes ( void /* newfacet_list */);
+facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew);
+facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew);
+void    qh_matchneighbor (facetT *newfacet, int newskip, int hashsize,
+                         int *hashcount);
+void   qh_matchnewfacets (void);
+boolT   qh_matchvertices (int firstindex, setT *verticesA, int skipA, 
+                         setT *verticesB, int *skipB, boolT *same);
+facetT *qh_newfacet(void);
+ridgeT *qh_newridge(void);
+int     qh_pointid (pointT *point);
+void   qh_removefacet(facetT *facet);
+void   qh_removevertex(vertexT *vertex);
+void    qh_updatevertices (void);
+
+
+/*========== -prototypes poly2.c in alphabetical order ===========*/
+
+void    qh_addhash (void* newelem, setT *hashtable, int hashsize, unsigned hash);
+void   qh_check_bestdist (void);
+void    qh_check_maxout (void);
+void    qh_check_output (void);
+void    qh_check_point (pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2);
+void           qh_check_points(void);
+void   qh_checkconvex(facetT *facetlist, int fault);
+void    qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp);
+void   qh_checkflipped_all (facetT *facetlist);
+void   qh_checkpolygon(facetT *facetlist);
+void    qh_checkvertex (vertexT *vertex);
+void   qh_clearcenters (qh_CENTER type);
+void   qh_createsimplex(setT *vertices);
+void   qh_delridge(ridgeT *ridge);
+void    qh_delvertex (vertexT *vertex);
+setT   *qh_facet3vertex (facetT *facet);
+facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
+           realT *bestdist, boolT *isoutside);
+facetT *qh_findfacet_all (pointT *point, realT *bestdist, boolT *isoutside,
+                         int *numpart);
+int    qh_findgood (facetT *facetlist, int goodhorizon);
+void   qh_findgood_all (facetT *facetlist);
+void    qh_furthestnext (void /* qh facet_list */);
+void    qh_furthestout (facetT *facet);
+void    qh_infiniteloop (facetT *facet);
+void   qh_initbuild(void);
+void   qh_initialhull(setT *vertices);
+setT   *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints);
+vertexT *qh_isvertex (pointT *point, setT *vertices);
+vertexT *qh_makenewfacets (pointT *point /*horizon_list, visible_list*/);
+void    qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount);
+void    qh_nearcoplanar ( void /* qh.facet_list */);
+vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
+int    qh_newhashtable(int newsize);
+vertexT *qh_newvertex(pointT *point);
+ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp);
+void    qh_outcoplanar (void /* facet_list */);
+pointT *qh_point (int id);
+void   qh_point_add (setT *set, pointT *point, void *elem);
+setT   *qh_pointfacet (void /*qh facet_list*/);
+setT   *qh_pointvertex (void /*qh facet_list*/);
+void   qh_prependfacet(facetT *facet, facetT **facetlist);
+void   qh_printhashtable(FILE *fp);
+void    qh_printlists (void);
+void    qh_resetlists (boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/);
+void    qh_setvoronoi_all (void);
+void   qh_triangulate (void /*qh facet_list*/);
+void    qh_triangulate_facet (facetT *facetA, vertexT **first_vertex);
+void    qh_triangulate_link (facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB);
+void   qh_triangulate_mirror (facetT *facetA, facetT *facetB);
+void    qh_triangulate_null (facetT *facetA);
+void    qh_vertexintersect(setT **vertexsetA,setT *vertexsetB);
+setT   *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB);
+void    qh_vertexneighbors (void /*qh facet_list*/);
+boolT  qh_vertexsubset(setT *vertexsetA, setT *vertexsetB);
+
+
+#endif /* qhDEFpoly */
diff --git a/extern/qhull/include/qhull/qhull.h b/extern/qhull/include/qhull/qhull.h
new file mode 100755 (executable)
index 0000000..896ec1e
--- /dev/null
@@ -0,0 +1,1048 @@
+/*<html><pre>  -<a                             href="qh-qhull.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   qhull.h
+   user-level header file for using qhull.a library
+
+   see qh-qhull.htm, qhull_a.h
+
+   copyright (c) 1993-2002, The Geometry Center
+
+   NOTE: access to qh_qh is via the 'qh' macro.  This allows
+   qh_qh to be either a pointer or a structure.  An example
+   of using qh is "qh DROPdim" which accesses the DROPdim
+   field of qh_qh.  Similarly, access to qh_qhstat is via
+   the 'qhstat' macro.
+
+   includes function prototypes for qhull.c, geom.c, global.c, io.c, user.c
+
+   use mem.h for mem.c
+   use qset.h for qset.c
+
+   see unix.c for an example of using qhull.h
+
+   recompile qhull if you change this file
+*/
+
+#ifndef qhDEFqhull
+#define qhDEFqhull 1
+
+/*=========================== -included files ==============*/
+
+#include <setjmp.h>
+#include <float.h>
+#include <time.h>
+
+#if __MWERKS__ && __POWERPC__
+#include  <SIOUX.h>
+#include  <Files.h>
+#include       <Desk.h>
+#endif
+
+#ifndef __STDC__
+#ifndef __cplusplus
+#if     !_MSC_VER
+#error  Neither __STDC__ nor __cplusplus is defined.  Please use strict ANSI C or C++ to compile
+#error  Qhull.  You may need to turn off compiler extensions in your project configuration.  If
+#error  your compiler is a standard C compiler, you can delete this warning from qhull.h
+#endif
+#endif
+#endif
+
+#include "user.h"      /* user defineable constants */
+
+/*============ constants and basic types ====================*/
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="qh_VERSION">-</a>
+
+  qh_VERSION
+    version string by year and date
+
+    the revision increases on code changes only
+
+  notes:
+    change date:    Changes.txt, Announce.txt, README.txt, qhull.man
+                    qhull-news.html, Eudora signatures, 
+    change version: README.txt, qhull.html, file_id.diz, Makefile
+    change year:    Copying.txt
+    check download size
+    recompile user_eg.c, rbox.c, qhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c
+    make copy of qhull-news.html as qh-news.htm
+*/
+
+#define qh_VERSION "2002.1 2002/8/20"
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="coordT">-</a>
+
+  coordT
+    coordinates and coefficients are stored as realT (i.e., double)
+
+  notes:
+    could use 'float' for data and 'double' for calculations (realT vs. coordT)
+      This requires many type casts, and adjusted error bounds.
+      Also C compilers may do expressions in double anyway.
+*/
+#define coordT realT
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="pointT">-</a>
+
+  pointT
+    a point is an array of DIM3 coordinates
+*/
+#define pointT coordT
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="flagT">-</a>
+
+  flagT
+    Boolean flag as a bit
+*/
+#define flagT unsigned int
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="boolT">-</a>
+
+  boolT
+    boolean value, either True or False
+
+  notes:
+    needed for portability
+*/
+#define boolT unsigned int
+#ifdef False
+#undef False
+#endif
+#ifdef True
+#undef True
+#endif
+#define False 0
+#define True 1
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="CENTERtype">-</a>
+
+  qh_CENTER
+    to distinguish facet->center
+*/
+typedef enum
+{
+    qh_ASnone = 0, qh_ASvoronoi, qh_AScentrum
+}
+qh_CENTER;
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="qh_PRINT">-</a>
+
+  qh_PRINT
+    output formats for printing (qh.PRINTout).
+    'Fa' 'FV' 'Fc' 'FC' 
+       
+
+   notes:
+   some of these names are similar to qh names.  The similar names are only
+   used in switch statements in qh_printbegin() etc.
+*/
+typedef enum {qh_PRINTnone= 0, 
+  qh_PRINTarea, qh_PRINTaverage,           /* 'Fa' 'FV' 'Fc' 'FC' */
+  qh_PRINTcoplanars, qh_PRINTcentrums, 
+  qh_PRINTfacets, qh_PRINTfacets_xridge,   /* 'f' 'FF' 'G' 'FI' 'Fi' 'Fn' */
+  qh_PRINTgeom, qh_PRINTids, qh_PRINTinner, qh_PRINTneighbors, 
+  qh_PRINTnormals, qh_PRINTouter,          /* 'n' 'Fo' 'i' 'm' 'Fm' 'o' */
+  qh_PRINTincidences, qh_PRINTmathematica, qh_PRINTmerges, qh_PRINToff, 
+  qh_PRINToptions, qh_PRINTpointintersect, /* 'FO' 'Fp' 'FP' 'p' 'FQ' 'FS' */
+  qh_PRINTpointnearest, qh_PRINTpoints, qh_PRINTqhull, qh_PRINTsize, 
+  qh_PRINTsummary, qh_PRINTtriangles,      /* 'Fs' 'Ft' 'Fv' 'FN' 'Fx' */
+  qh_PRINTvertices, qh_PRINTvneighbors, qh_PRINTextremes,
+  qh_PRINTEND} qh_PRINT;
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="qh_ALL">-</a>
+
+  qh_ALL
+    argument flag for selecting everything
+*/
+#define qh_ALL      True
+#define qh_NOupper  True     /* argument for qh_findbest */
+#define qh_IScheckmax  True     /* argument for qh_findbesthorizon */
+#define qh_ISnewfacets  True     /* argument for qh_findbest */
+#define qh_RESETvisible  True     /* argument for qh_resetlists */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="qh_ERR">-</a>
+
+  qh_ERR
+    Qhull exit codes, for indicating errors
+*/
+#define qh_ERRnone  0    /* no error occurred during qhull */
+#define qh_ERRinput 1    /* input inconsistency */
+#define qh_ERRsingular 2 /* singular input data */
+#define qh_ERRprec  3    /* precision error */
+#define qh_ERRmem   4    /* insufficient memory, matches mem.h */
+#define qh_ERRqhull 5    /* internal error detected, matches mem.h */
+
+/* ============ -structures- ====================
+   each of the following structures is defined by a typedef
+   all realT and coordT fields occur at the beginning of a structure
+        (otherwise space may be wasted due to alignment)
+   define all flags together and pack into 32-bit number
+*/
+
+typedef struct vertexT vertexT;
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT;          /* defined in qset.h */
+#endif
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="facetT">-</a>
+
+  facetT
+    defines a facet
+
+  notes:
+   qhull() generates the hull as a list of facets.
+
+  topological information:
+    f.previous,next     doubly-linked list of facets
+    f.vertices          set of vertices
+    f.ridges            set of ridges
+    f.neighbors         set of neighbors
+    f.toporient         True if facet has top-orientation (else bottom)
+
+  geometric information:
+    f.offset,normal     hyperplane equation
+    f.maxoutside        offset to outer plane -- all points inside
+    f.center            centrum for testing convexity
+    f.simplicial        True if facet is simplicial
+    f.flipped           True if facet does not include qh.interior_point
+
+  for constructing hull:
+    f.visible           True if facet on list of visible facets (will be deleted)
+    f.newfacet          True if facet on list of newly created facets
+    f.coplanarset       set of points coplanar with this facet
+                        (includes near-inside points for later testing)
+    f.outsideset        set of points outside of this facet
+    f.furthestdist      distance to furthest point of outside set
+    f.visitid           marks visited facets during a loop
+    f.replace           replacement facet for to-be-deleted, visible facets
+    f.samecycle,newcycle cycle of facets for merging into horizon facet
+
+  see below for other flags and fields
+*/
+struct facetT {
+#if !qh_COMPUTEfurthest
+  coordT   furthestdist;/* distance to furthest point of outsideset */
+#endif
+#if qh_MAXoutside
+  coordT   maxoutside;  /* max computed distance of point to facet
+                       Before QHULLfinished this is an approximation
+                       since maxdist not always set for mergefacet
+                       Actual outer plane is +DISTround and
+                       computed outer plane is +2*DISTround */
+#endif
+  coordT   offset;      /* exact offset of hyperplane from origin */
+  coordT  *normal;      /* normal of hyperplane, hull_dim coefficients */
+                       /*   if tricoplanar, shared with a neighbor */
+  union {               /* in order of testing */
+   realT   area;        /* area of facet, only in io.c if  ->isarea */
+   facetT *replace;    /*  replacement facet if ->visible and NEWfacets
+                            is NULL only if qh_mergedegen_redundant or interior */
+   facetT *samecycle;   /*  cycle of facets from the same visible/horizon intersection,
+                            if ->newfacet */
+   facetT *newcycle;    /*  in horizon facet, current samecycle of new facets */ 
+   facetT *trivisible;  /* visible facet for ->tricoplanar facets during qh_triangulate() */
+   facetT *triowner;    /* owner facet for ->tricoplanar, !isarea facets w/ ->keepcentrum */
+  }f;
+  coordT  *center;      /*  centrum for convexity, qh CENTERtype == qh_AScentrum */
+                       /*  Voronoi center, qh CENTERtype == qh_ASvoronoi */
+                       /*   if tricoplanar, shared with a neighbor */
+  facetT  *previous;    /* previous facet in the facet_list */
+  facetT  *next;        /* next facet in the facet_list */
+  setT    *vertices;    /* vertices for this facet, inverse sorted by ID 
+                           if simplicial, 1st vertex was apex/furthest */
+  setT    *ridges;      /* explicit ridges for nonsimplicial facets.
+                          for simplicial facets, neighbors defines ridge */
+  setT    *neighbors;   /* neighbors of the facet.  If simplicial, the kth
+                          neighbor is opposite the kth vertex, and the first
+                          neighbor is the horizon facet for the first vertex*/
+  setT    *outsideset;  /* set of points outside this facet
+                          if non-empty, last point is furthest
+                          if NARROWhull, includes coplanars for partitioning*/
+  setT    *coplanarset; /* set of points coplanar with this facet
+                          > qh.min_vertex and <= facet->max_outside
+                           a point is assigned to the furthest facet
+                          if non-empty, last point is furthest away */
+  unsigned visitid;     /* visit_id, for visiting all neighbors,
+                          all uses are independent */
+  unsigned id;         /* unique identifier from qh facet_id */
+  unsigned nummerge:9;  /* number of merges */
+#define qh_MAXnummerge 511 /*     2^9-1, 32 flags total, see "flags:" in io.c */
+  flagT    tricoplanar:1; /* True if TRIangulate and simplicial and coplanar with a neighbor */
+                         /*   all tricoplanars share the same ->center, ->normal, ->offset, ->maxoutside */
+                         /*   all tricoplanars share the same apex */
+                          /*   if ->degenerate, does not span facet (one logical ridge) */
+                          /*   one tricoplanar has ->keepcentrum and ->coplanarset */
+                          /*   during qh_triangulate, f.trivisible points to original facet */
+  flagT           newfacet:1;  /* True if facet on qh newfacet_list (new or merged) */
+  flagT           visible:1;   /* True if visible facet (will be deleted) */
+  flagT    toporient:1; /* True if created with top orientation
+                          after merging, use ridge orientation */
+  flagT    simplicial:1;/* True if simplicial facet, ->ridges may be implicit */
+  flagT    seen:1;      /* used to perform operations only once, like visitid */
+  flagT    seen2:1;     /* used to perform operations only once, like visitid */
+  flagT           flipped:1;   /* True if facet is flipped */
+  flagT    upperdelaunay:1; /* True if facet is upper envelope of Delaunay triangulation */
+  flagT    notfurthest:1; /* True if last point of outsideset is not furthest*/
+
+/*-------- flags primarily for output ---------*/
+  flagT           good:1;      /* True if a facet marked good for output */
+  flagT    isarea:1;    /* True if facet->f.area is defined */
+
+/*-------- flags for merging ------------------*/
+  flagT    dupridge:1;  /* True if duplicate ridge in facet */
+  flagT    mergeridge:1; /* True if facet or neighbor contains a qh_MERGEridge
+                            ->normal defined (also defined for mergeridge2) */
+  flagT    mergeridge2:1; /* True if neighbor contains a qh_MERGEridge (mark_dupridges */
+  flagT    coplanar:1;  /* True if horizon facet is coplanar at last use */
+  flagT     mergehorizon:1; /* True if will merge into horizon (->coplanar) */
+  flagT            cycledone:1;/* True if mergecycle_all already done */
+  flagT    tested:1;    /* True if facet convexity has been tested (false after merge */
+  flagT    keepcentrum:1; /* True if keep old centrum after a merge, or marks owner for ->tricoplanar */
+  flagT           newmerge:1;  /* True if facet is newly merged for reducevertices */
+  flagT           degenerate:1; /* True if facet is degenerate (degen_mergeset or ->tricoplanar) */
+  flagT           redundant:1;  /* True if facet is redundant (degen_mergeset) */
+};
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="ridgeT">-</a>
+
+  ridgeT
+    defines a ridge
+
+  notes:
+  a ridge is DIM3-1 simplex between two neighboring facets.  If the
+  facets are non-simplicial, there may be more than one ridge between
+  two facets.  E.G. a 4-d hypercube has two triangles between each pair
+  of neighboring facets.
+
+  topological information:
+    vertices            a set of vertices
+    top,bottom          neighboring facets with orientation
+
+  geometric information:
+    tested              True if ridge is clearly convex
+    nonconvex           True if ridge is non-convex
+*/
+struct ridgeT {
+  setT    *vertices;    /* vertices belonging to this ridge, inverse sorted by ID 
+                           NULL if a degen ridge (matchsame) */
+  facetT  *top;         /* top facet this ridge is part of */
+  facetT  *bottom;      /* bottom facet this ridge is part of */
+  unsigned id:24;       /* unique identifier, =>room for 8 flags */
+  flagT    seen:1;      /* used to perform operations only once */
+  flagT    tested:1;    /* True when ridge is tested for convexity */
+  flagT    nonconvex:1; /* True if getmergeset detected a non-convex neighbor
+                          only one ridge between neighbors may have nonconvex */
+};
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="vertexT">-</a>
+
+  vertexT
+     defines a vertex
+
+  topological information:
+    next,previous       doubly-linked list of all vertices
+    neighbors           set of adjacent facets (only if qh.VERTEXneighbors)
+
+  geometric information:
+    point               array of DIM3 coordinates
+*/
+struct vertexT {
+  vertexT *next;        /* next vertex in vertex_list */
+  vertexT *previous;    /* previous vertex in vertex_list */
+  pointT  *point;       /* hull_dim coordinates (coordT) */
+  setT    *neighbors;   /* neighboring facets of vertex, qh_vertexneighbors()
+                          inits in io.c or after first merge */
+  unsigned visitid; /* for use with qh vertex_visit */
+  unsigned id:24;   /* unique identifier, =>room for 8 flags */
+  flagT    seen:1;      /* used to perform operations only once */
+  flagT    seen2:1;     /* another seen flag */
+  flagT    delridge:1;  /* vertex was part of a deleted ridge */
+  flagT           deleted:1;   /* true if vertex on qh del_vertices */
+  flagT    newlist:1;   /* true if vertex on qh newvertex_list */
+};
+
+/*======= -global variables -qh ============================*/
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh">-</a>
+
+  qh
+   all global variables for qhull are in qh, qhmem, and qhstat
+
+  notes:
+   qhmem is defined in mem.h and qhstat is defined in stat.h
+   access to qh_qh is via the "qh" macro.  See qh_QHpointer in user.h
+*/
+typedef struct qhT qhT;
+#if qh_QHpointer
+#define qh qh_qh->
+extern qhT *qh_qh;     /* allocated in global.c */
+#else
+#define qh qh_qh.
+extern qhT qh_qh;
+#endif
+
+struct qhT {
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-const">-</a>
+
+  qh constants
+    configuration flags and constants for Qhull
+
+  notes:
+    The user configures Qhull by defining flags.  They are
+    copied into qh by qh_setflags().  qh-quick.htm#options defines the flags.
+*/
+  boolT ALLpoints;        /* true 'Qs' if search all points for initial simplex */
+  boolT ANGLEmerge;      /* true 'Qa' if sort potential merges by angle */
+  boolT APPROXhull;       /* true 'Wn' if MINoutside set */
+  realT MINoutside;       /*   'Wn' min. distance for an outside point */
+  boolT ATinfinity;       /* true 'Qz' if point num_points-1 is "at-infinity"
+                             for improving precision in Delaunay triangulations */
+  boolT AVOIDold;         /* true 'Q4' if avoid old->new merges */
+  boolT BESToutside;      /* true 'Qf' if partition points into best outsideset */
+  boolT CDDinput;         /* true 'Pc' if input uses CDD format (1.0/offset first) */
+  boolT CDDoutput;        /* true 'PC' if print normals in CDD format (offset first) */
+  boolT CHECKfrequently;  /* true 'Tc' if checking frequently */
+  realT premerge_cos;     /*   'A-n'   cos_max when pre merging */
+  realT postmerge_cos;    /*   'An'    cos_max when post merging */
+  boolT DELAUNAY;         /* true 'd' if computing DELAUNAY triangulation */
+  boolT DOintersections;  /* true 'Gh' if print hyperplane intersections */
+  int   DROPdim;          /* drops dim 'GDn' for 4-d -> 3-d output */
+  boolT FORCEoutput;      /* true 'Po' if forcing output despite degeneracies */
+  int   GOODpoint;        /* 1+n for 'QGn', good facet if visible/not(-) from point n*/
+  pointT *GOODpointp;     /*   the actual point */
+  boolT GOODthreshold;    /* true if qh lower_threshold/upper_threshold defined
+                            false if qh SPLITthreshold */
+  int   GOODvertex;       /* 1+n, good facet if vertex for point n */
+  pointT *GOODvertexp;     /*   the actual point */
+  boolT HALFspace;        /* true 'Hn,n,n' if halfspace intersection */
+  int   IStracing;        /* trace execution, 0=none, 1=least, 4=most, -1=events */
+  int   KEEParea;         /* 'PAn' number of largest facets to keep */
+  boolT KEEPcoplanar;     /* true 'Qc' if keeping nearest facet for coplanar points */
+  boolT KEEPinside;       /* true 'Qi' if keeping nearest facet for inside points
+                             set automatically if 'd Qc' */
+  int   KEEPmerge;        /* 'PMn' number of facets to keep with most merges */
+  realT KEEPminArea;      /* 'PFn' minimum facet area to keep */
+  realT MAXcoplanar;      /* 'Un' max distance below a facet to be coplanar*/
+  boolT MERGEexact;      /* true 'Qx' if exact merges (coplanar, degen, dupridge, flipped) */
+  boolT MERGEindependent; /* true 'Q2' if merging independent sets */
+  boolT MERGING;          /* true if exact-, pre- or post-merging, with angle and centrum tests */
+  realT   premerge_centrum;  /*   'C-n' centrum_radius when pre merging.  Default is round-off */
+  realT   postmerge_centrum; /*   'Cn' centrum_radius when post merging.  Default is round-off */
+  boolT MERGEvertices;   /* true 'Q3' if merging redundant vertices */
+  realT MINvisible;       /* 'Vn' min. distance for a facet to be visible */
+  boolT NOnarrow;         /* true 'Q10' if no special processing for narrow distributions */
+  boolT NOnearinside;     /* true 'Q8' if ignore near-inside points when partitioning */
+  boolT NOpremerge;       /* true 'Q0' if no defaults for C-0 or Qx */
+  boolT ONLYgood;        /* true 'Qg' if process points with good visible or horizon facets */
+  boolT ONLYmax;         /* true 'Qm' if only process points that increase max_outside */
+  boolT PICKfurthest;     /* true 'Q9' if process furthest of furthest points*/
+  boolT POSTmerge;        /* true if merging after buildhull (Cn or An) */
+  boolT PREmerge;         /* true if merging during buildhull (C-n or A-n) */
+                       /* NOTE: some of these names are similar to qh_PRINT names */
+  boolT PRINTcentrums;   /* true 'Gc' if printing centrums */
+  boolT PRINTcoplanar;    /* true 'Gp' if printing coplanar points */
+  int  PRINTdim;         /* print dimension for Geomview output */
+  boolT PRINTdots;        /* true 'Ga' if printing all points as dots */
+  boolT PRINTgood;        /* true 'Pg' if printing good facets */
+  boolT PRINTinner;      /* true 'Gi' if printing inner planes */
+  boolT PRINTneighbors;          /* true 'PG' if printing neighbors of good facets */
+  boolT PRINTnoplanes;   /* true 'Gn' if printing no planes */
+  boolT PRINToptions1st;  /* true 'FO' if printing options to stderr */
+  boolT PRINTouter;      /* true 'Go' if printing outer planes */
+  boolT PRINTprecision;   /* false 'Pp' if not reporting precision problems */
+  qh_PRINT PRINTout[qh_PRINTEND]; /* list of output formats to print */
+  boolT PRINTridges;      /* true 'Gr' if print ridges */
+  boolT PRINTspheres;     /* true 'Gv' if print vertices as spheres */
+  boolT PRINTstatistics;  /* true 'Ts' if printing statistics to stderr */
+  boolT PRINTsummary;     /* true 's' if printing summary to stderr */
+  boolT PRINTtransparent; /* true 'Gt' if print transparent outer ridges */
+  boolT PROJECTdelaunay;  /* true if DELAUNAY, no readpoints() and
+                            need projectinput() for Delaunay in qh_init_B */
+  int   PROJECTinput;     /* number of projected dimensions 'bn:0Bn:0' */
+  boolT QUICKhelp;       /* true if quick help message for degen input */
+  boolT RANDOMdist;       /* true if randomly change distplane and setfacetplane */
+  realT RANDOMfactor;     /*    maximum random perturbation */
+  realT RANDOMa;         /*  qh_randomfactor is randr * RANDOMa + RANDOMb */
+  realT RANDOMb;
+  boolT RANDOMoutside;    /* true if select a random outside point */
+  int  REPORTfreq;       /* buildtracing reports every n facets */
+  int   REPORTfreq2;     /* tracemerging reports every REPORTfreq/2 facets */
+  int  RERUN;            /* 'TRn' rerun qhull n times (qh.build_cnt) */
+  int  ROTATErandom;     /* 'QRn' seed, 0 time, >= rotate input */
+  boolT SCALEinput;       /* true 'Qbk' if scaling input */
+  boolT SCALElast;        /* true 'Qbb' if scale last coord to max prev coord */
+  boolT SETroundoff;      /* true 'E' if qh DISTround is predefined */
+  boolT SKIPcheckmax;    /* true 'Q5' if skip qh_check_maxout */
+  boolT SKIPconvex;       /* true 'Q6' if skip convexity testing during pre-merge */
+  boolT SPLITthresholds;  /* true if upper_/lower_threshold defines a region
+                               used only for printing (not for qh ONLYgood) */
+  int  STOPcone;         /* 'TCn' 1+n for stopping after cone for point n*/
+                         /*       also used by qh_build_withresart for err exit*/
+  int  STOPpoint;        /* 'TVn' 'TV-n' 1+n for stopping after/before(-)
+                                       adding point n */
+  int  TESTpoints;       /* 'QTn' num of test points after qh.num_points.  Test points always coplanar. */
+  boolT TESTvneighbors;   /*  true 'Qv' if test vertex neighbors at end */
+  int   TRACElevel;       /* 'Tn' conditional IStracing level */
+  int  TRACElastrun;     /*  qh.TRACElevel applies to last qh.RERUN */
+  int   TRACEpoint;       /* 'TPn' start tracing when point n is a vertex */
+  realT TRACEdist;        /* 'TWn' start tracing when merge distance too big */
+  int   TRACEmerge;       /* 'TMn' start tracing before this merge */
+  boolT TRIangulate;     /* true 'Qt' if triangulate non-simplicial facets */
+  boolT TRInormals;      /* true 'Q11' if triangulate duplicates normals (sets Qt) */
+  boolT UPPERdelaunay;    /* true 'Qu' if computing furthest-site Delaunay */
+  boolT VERIFYoutput;     /* true 'Tv' if verify output at end of qhull */
+  boolT VIRTUALmemory;    /* true 'Q7' if depth-first processing in buildhull */
+  boolT VORONOI;         /* true 'v' if computing Voronoi diagram */
+
+  /*--------input constants ---------*/
+  realT AREAfactor;       /* 1/(hull_dim-1)! for converting det's to area */
+  boolT DOcheckmax;       /* true if calling qh_check_maxout (qh_initqhull_globals) */
+  char *feasible_string;  /* feasible point 'Hn,n,n' for halfspace intersection */
+  coordT *feasible_point;  /*    as coordinates, both malloc'd */
+  boolT GETarea;          /* true 'Fa', 'FA', 'FS', 'PAn', 'PFn' if compute facet area/Voronoi volume in io.c */
+  boolT KEEPnearinside;   /* true if near-inside points in coplanarset */
+  int  hull_dim;         /* dimension of hull, set by initbuffers */
+  int  input_dim;        /* dimension of input, set by initbuffers */
+  int  num_points;       /* number of input points */
+  pointT *first_point;    /* array of input points, see POINTSmalloc */
+  boolT POINTSmalloc;     /*   true if qh first_point/num_points allocated */
+  pointT *input_points;   /* copy of original qh.first_point for input points for qh_joggleinput */
+  boolT input_malloc;     /* true if qh input_points malloc'd */
+  char         qhull_command[256];/* command line that invoked this program */
+  char         rbox_command[256]; /* command line that produced the input points */
+  char  qhull_options[512];/* descriptive list of options */
+  int   qhull_optionlen;  /*    length of last line */
+  int   qhull_optionsiz;  /*     size of qhull_options before qh_initbuild */
+  boolT VERTEXneighbors;  /* true if maintaining vertex neighbors */
+  boolT ZEROcentrum;      /* true if 'C-0' or 'C-0 Qx'.  sets ZEROall_ok */
+  realT *upper_threshold; /* don't print if facet->normal[k]>=upper_threshold[k]
+                             must set either GOODthreshold or SPLITthreshold
+                            if Delaunay, default is 0.0 for upper envelope */
+  realT *lower_threshold; /* don't print if facet->normal[k] <=lower_threshold[k] */
+  realT *upper_bound;     /* scale point[k] to new upper bound */
+  realT *lower_bound;     /* scale point[k] to new lower bound
+                            project if both upper_ and lower_bound == 0 */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-prec">-</a>
+
+  qh precision constants
+    precision constants for Qhull
+
+  notes:
+    qh_detroundoff() computes the maximum roundoff error for distance
+    and other computations.  It also sets default values for the
+    qh constants above.
+*/
+  realT ANGLEround;       /* max round off error for angles */
+  realT centrum_radius;   /* max centrum radius for convexity (roundoff added) */
+  realT cos_max;         /* max cosine for convexity (roundoff added) */
+  realT DISTround;        /* max round off error for distances, 'E' overrides */
+  realT MAXabs_coord;     /* max absolute coordinate */
+  realT MAXlastcoord;     /* max last coordinate for qh_scalelast */
+  realT MAXsumcoord;      /* max sum of coordinates */
+  realT MAXwidth;         /* max rectilinear width of point coordinates */
+  realT MINdenom_1;       /* min. abs. value for 1/x */
+  realT MINdenom;         /*    use divzero if denominator < MINdenom */
+  realT MINdenom_1_2;     /* min. abs. val for 1/x that allows normalization */
+  realT MINdenom_2;       /*    use divzero if denominator < MINdenom_2 */
+  realT MINlastcoord;     /* min. last coordinate for qh_scalelast */
+  boolT NARROWhull;       /* set in qh_initialhull if angle < qh_MAXnarrow */
+  realT *NEARzero;        /* hull_dim array for near zero in gausselim */
+  realT NEARinside;       /* keep points for qh_check_maxout if close to facet */
+  realT ONEmerge;         /* max distance for merging simplicial facets */
+  realT outside_err;      /* application's epsilon for coplanar points
+                             qh_check_bestdist() qh_check_points() reports error if point outside */
+  realT WIDEfacet;        /* size of wide facet for skipping ridge in
+                            area computation and locking centrum */
+  
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-intern">-</a>
+
+  qh internal constants
+    internal constants for Qhull
+*/
+  char qhull[sizeof("qhull")]; /* for checking ownership */
+  void *old_stat;         /* pointer to saved qh_qhstat, qh_save_qhull */
+  jmp_buf errexit;        /* exit label for qh_errexit, defined by setjmp() */
+  char jmpXtra[40];       /* extra bytes in case jmp_buf is defined wrong by compiler */
+  jmp_buf restartexit;    /* restart label for qh_errexit, defined by setjmp() */
+  char jmpXtra2[40];      /* extra bytes in case jmp_buf is defined wrong by compiler*/
+  FILE *fin;              /* pointer to input file, init by qh_meminit */
+  FILE *fout;             /* pointer to output file */
+  FILE *ferr;             /* pointer to error file */
+  pointT *interior_point; /* center point of the initial simplex*/
+  int   normal_size;      /* size in bytes for facet normals and point coords*/
+  int   center_size;      /* size in bytes for Voronoi centers */
+  int   TEMPsize;         /* size for small, temporary sets (in quick mem) */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-lists">-</a>
+
+  qh facet and vertex lists
+    defines lists of facets, new facets, visible facets, vertices, and
+    new vertices.  Includes counts, next ids, and trace ids.
+  see:
+    qh_resetlists()
+*/
+  facetT *facet_list;     /* first facet */
+  facetT  *facet_tail;     /* end of facet_list (dummy facet) */
+  facetT *facet_next;     /* next facet for buildhull()
+                            previous facets do not have outside sets
+                             NARROWhull: previous facets may have coplanar outside sets for qh_outcoplanar */
+  facetT *newfacet_list;  /* list of new facets to end of facet_list */
+  facetT *visible_list;   /* list of visible facets preceeding newfacet_list,
+                             facet->visible set */
+  int       num_visible;  /* current number of visible facets */
+  unsigned tracefacet_id;  /* set at init, then can print whenever */
+  facetT *tracefacet;     /*   set in newfacet/mergefacet, undone in delfacet*/
+  unsigned tracevertex_id;  /* set at buildtracing, can print whenever */
+  vertexT *tracevertex;     /*   set in newvertex, undone in delvertex*/
+  vertexT *vertex_list;     /* list of all vertices, to vertex_tail */
+  vertexT  *vertex_tail;    /*      end of vertex_list (dummy vertex) */
+  vertexT *newvertex_list; /* list of vertices in newfacet_list, to vertex_tail
+                             all vertices have 'newlist' set */
+  int  num_facets;       /* number of facets in facet_list
+                            includes visble faces (num_visible) */
+  int  num_vertices;     /* number of vertices in facet_list */
+  int   num_outside;      /* number of points in outsidesets (for tracing and RANDOMoutside)
+                               includes coplanar outsideset points for NARROWhull/qh_outcoplanar() */
+  int   num_good;         /* number of good facets (after findgood_all) */
+  unsigned facet_id;      /* ID of next, new facet from newfacet() */
+  unsigned ridge_id;      /* ID of next, new ridge from newridge() */
+  unsigned vertex_id;     /* ID of next, new vertex from newvertex() */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-var">-</a>
+
+  qh global variables
+    defines minimum and maximum distances, next visit ids, several flags,
+    and other global variables.
+    initialize in qh_initbuild or qh_maxmin if used in qh_buildhull
+*/
+  unsigned long hulltime; /* ignore time to set up input and randomize */
+                          /*   use unsigned to avoid wrap-around errors */
+  boolT ALLOWrestart;     /* true if qh_precision can use qh.restartexit */
+  int   build_cnt;        /* number of calls to qh_initbuild */
+  qh_CENTER CENTERtype;   /* current type of facet->center, qh_CENTER */
+  int  furthest_id;      /* pointid of furthest point, for tracing */
+  facetT *GOODclosest;    /* closest facet to GOODthreshold in qh_findgood */
+  realT JOGGLEmax;        /* set 'QJn' if randomly joggle input */
+  boolT maxoutdone;       /* set qh_check_maxout(), cleared by qh_addpoint() */
+  realT max_outside;      /* maximum distance from a point to a facet,
+                              before roundoff, not simplicial vertices
+                              actual outer plane is +DISTround and
+                              computed outer plane is +2*DISTround */
+  realT max_vertex;       /* maximum distance (>0) from vertex to a facet,
+                              before roundoff, due to a merge */
+  realT min_vertex;       /* minimum distance (<0) from vertex to a facet,
+                              before roundoff, due to a merge
+                              if qh.JOGGLEmax, qh_makenewplanes sets it
+                              recomputed if qh.DOcheckmax, default -qh.DISTround */
+  boolT NEWfacets;        /* true while visible facets invalid due to new or merge
+                             from makecone/attachnewfacets to deletevisible */
+  boolT findbestnew;     /* true if partitioning calls qh_findbestnew */
+  boolT findbest_notsharp; /* true if new facets are at least 90 degrees */
+  boolT NOerrexit;        /* true if qh.errexit is not available */
+  realT PRINTcradius;     /* radius for printing centrums */
+  realT PRINTradius;      /* radius for printing vertex spheres and points */
+  boolT POSTmerging;      /* true when post merging */
+  int  printoutvar;      /* temporary variable for qh_printbegin, etc. */
+  int  printoutnum;      /* number of facets printed */
+  boolT QHULLfinished;    /* True after qhull() is finished */
+  realT totarea;          /* 'FA': total facet area computed by qh_getarea */
+  realT totvol;           /* 'FA': total volume computed by qh_getarea */
+  unsigned int visit_id;  /* unique ID for searching neighborhoods, */
+  unsigned int vertex_visit; /* unique ID for searching vertices */
+  boolT ZEROall_ok;       /* True if qh_checkzero always succeeds */
+  boolT WAScoplanar;      /* True if qh_partitioncoplanar (qh_check_maxout) */
+  
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-set">-</a>
+
+  qh global sets
+    defines sets for merging, initial simplex, hashing, extra input points,
+    and deleted vertices
+*/
+  setT *facet_mergeset;   /* temporary set of merges to be done */
+  setT *degen_mergeset;   /* temporary set of degenerate and redundant merges */
+  setT *hash_table;      /* hash table for matching ridges in qh_matchfacets
+                             size is setsize() */
+  setT *other_points;     /* additional points (first is qh interior_point) */
+  setT *del_vertices;     /* vertices to partition and delete with visible
+                             facets.  Have deleted set for checkfacet */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-buf">-</a>
+
+  qh global buffers
+    defines buffers for maxtrix operations, input, and error messages
+*/
+  coordT *gm_matrix;      /* (dim+1)Xdim matrix for geom.c */
+  coordT **gm_row;        /* array of gm_matrix rows */
+  char* line;             /* malloc'd input line of maxline+1 chars */
+  int maxline;
+  coordT *half_space;     /* malloc'd input array for halfspace (qh normal_size+coordT) */
+  coordT *temp_malloc;    /* malloc'd input array for points */
+  
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-static">-</a>
+
+  qh static variables
+    defines static variables for individual functions
+
+  notes:
+    do not use 'static' within a function.  Multiple instances of qhull
+    may exist.
+
+    do not assume zero initialization, 'QPn' may cause a restart
+*/
+  boolT ERREXITcalled;    /* true during errexit (prevents duplicate calls */
+  boolT firstcentrum;    /* for qh_printcentrum */
+  realT last_low;         /* qh_scalelast parameters for qh_setdelaunay */
+  realT last_high;
+  realT last_newhigh;
+  unsigned lastreport;    /* for qh_buildtracing */
+  int mergereport;        /* for qh_tracemerging */
+  boolT old_randomdist;   /* save RANDOMdist when io, tracing, or statistics */
+  int   ridgeoutnum;      /* number of ridges in 4OFF output */
+  void *old_qhstat;       /* for saving qh_qhstat in save_qhull() */
+  setT *old_tempstack;     /* for saving qhmem.tempstack in save_qhull */
+  setT *coplanarset;      /* set of coplanar facets for searching qh_findbesthorizon() */
+};
+
+/*=========== -macros- =========================*/
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="otherfacet_">-</a>
+
+  otherfacet_(ridge, facet)
+    return neighboring facet for a ridge in facet
+*/
+#define otherfacet_(ridge, facet) \
+                        (((ridge)->top == (facet)) ? (ridge)->bottom : (ridge)->top)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="getid_">-</a>
+
+  getid_(p)
+    return ID for facet, ridge, or vertex
+    return MAXINT if NULL (-1 causes type conversion error )
+*/
+#define getid_(p)       ((p) ? (p)->id : -1)
+
+/*============== FORALL macros ===================*/
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLfacets">-</a>
+
+  FORALLfacets { ... }
+    assign 'facet' to each facet in qh.facet_list
+
+  notes:
+    uses 'facetT *facet;'
+    assumes last facet is a sentinel
+
+  see:
+    FORALLfacet_( facetlist )
+*/
+#define FORALLfacets for (facet=qh facet_list;facet && facet->next;facet=facet->next)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLpoints">-</a>
+
+  FORALLpoints { ... }
+    assign 'point' to each point in qh.first_point, qh.num_points
+
+  declare:
+    coordT *point, *pointtemp;
+*/
+#define FORALLpoints FORALLpoint_(qh first_point, qh num_points)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLpoint_">-</a>
+
+  FORALLpoint_( points, num) { ... }
+    assign 'point' to each point in points array of num points
+
+  declare:
+    coordT *point, *pointtemp;
+*/
+#define FORALLpoint_(points, num) for(point= (points), \
+      pointtemp= (points)+qh hull_dim*(num); point < pointtemp; point += qh hull_dim)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLvertices">-</a>
+
+  FORALLvertices { ... }
+    assign 'vertex' to each vertex in qh.vertex_list
+
+  declare:
+    vertexT *vertex;
+
+  notes:
+    assumes qh.vertex_list terminated with a sentinel
+*/
+#define FORALLvertices for (vertex=qh vertex_list;vertex && vertex->next;vertex= vertex->next)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHfacet_">-</a>
+
+  FOREACHfacet_( facets ) { ... }
+    assign 'facet' to each facet in facets
+
+  declare:
+    facetT *facet, **facetp;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHfacet_(facets)    FOREACHsetelement_(facetT, facets, facet)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHneighbor_">-</a>
+
+  FOREACHneighbor_( facet ) { ... }
+    assign 'neighbor' to each neighbor in facet->neighbors
+
+  FOREACHneighbor_( vertex ) { ... }
+    assign 'neighbor' to each neighbor in vertex->neighbors
+
+  declare:
+    facetT *neighbor, **neighborp;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHneighbor_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighbor)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHpoint_">-</a>
+
+  FOREACHpoint_( points ) { ... }
+    assign 'point' to each point in points set
+
+  declare:
+    pointT *point, **pointp;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHpoint_(points)    FOREACHsetelement_(pointT, points, point)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHridge_">-</a>
+
+  FOREACHridge_( ridges ) { ... }
+    assign 'ridge' to each ridge in ridges set
+
+  declare:
+    ridgeT *ridge, **ridgep;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHridge_(ridges)    FOREACHsetelement_(ridgeT, ridges, ridge)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHvertex_">-</a>
+
+  FOREACHvertex_( vertices ) { ... }
+    assign 'vertex' to each vertex in vertices set
+
+  declare:
+    vertexT *vertex, **vertexp;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvertex_(vertices) FOREACHsetelement_(vertexT, vertices,vertex)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHfacet_i_">-</a>
+
+  FOREACHfacet_i_( facets ) { ... }
+    assign 'facet' and 'facet_i' for each facet in facets set
+
+  declare:
+    facetT *facet;
+    int     facet_n, facet_i;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHfacet_i_(facets)    FOREACHsetelement_i_(facetT, facets, facet)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHneighbor_i_">-</a>
+
+  FOREACHneighbor_i_( facet ) { ... }
+    assign 'neighbor' and 'neighbor_i' for each neighbor in facet->neighbors
+
+  FOREACHneighbor_i_( vertex ) { ... }
+    assign 'neighbor' and 'neighbor_i' for each neighbor in vertex->neighbors
+
+  declare:
+    facetT *neighbor;
+    int     neighbor_n, neighbor_i;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHneighbor_i_(facet)  FOREACHsetelement_i_(facetT, facet->neighbors, neighbor)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHpoint_i_">-</a>
+
+  FOREACHpoint_i_( points ) { ... }
+    assign 'point' and 'point_i' for each point in points set
+
+  declare:
+    pointT *point;
+    int     point_n, point_i;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHpoint_i_(points)    FOREACHsetelement_i_(pointT, points, point)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHridge_i_">-</a>
+
+  FOREACHridge_i_( ridges ) { ... }
+    assign 'ridge' and 'ridge_i' for each ridge in ridges set
+
+  declare:
+    ridgeT *ridge;
+    int     ridge_n, ridge_i;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHridge_i_(ridges)    FOREACHsetelement_i_(ridgeT, ridges, ridge)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHvertex_i_">-</a>
+
+  FOREACHvertex_i_( vertices ) { ... }
+    assign 'vertex' and 'vertex_i' for each vertex in vertices set
+
+  declare:
+    vertexT *vertex;
+    int     vertex_n, vertex_i;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+ */
+#define FOREACHvertex_i_(vertices) FOREACHsetelement_i_(vertexT, vertices,vertex)
+
+/********* -qhull.c prototypes (duplicated from qhull_a.h) **********************/
+
+void    qh_qhull (void);
+boolT   qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist);
+void   qh_printsummary(FILE *fp);
+
+/********* -user.c prototypes (alphabetical) **********************/
+
+void   qh_errexit(int exitcode, facetT *facet, ridgeT *ridge);
+void   qh_errprint(char* string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex);
+int     qh_new_qhull (int dim, int numpoints, coordT *points, boolT ismalloc,
+               char *qhull_cmd, FILE *outfile, FILE *errfile);
+void    qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall);
+void   qh_user_memsizes (void);
+
+/***** -geom.c/geom2.c prototypes (duplicated from geom.h) ****************/
+
+facetT *qh_findbest (pointT *point, facetT *startfacet,
+                    boolT bestoutside, boolT newfacets, boolT noupper,
+                    realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbestnew (pointT *point, facetT *startfacet,
+                     realT *dist, boolT bestoutside, boolT *isoutside, int *numpart);
+boolT   qh_gram_schmidt(int dim, realT **rows);
+void    qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
+void   qh_printsummary(FILE *fp);
+void    qh_projectinput (void);
+void    qh_randommatrix (realT *buffer, int dim, realT **row);
+void    qh_rotateinput (realT **rows);
+void    qh_scaleinput (void);
+void    qh_setdelaunay (int dim, int count, pointT *points);
+coordT  *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
+
+/***** -global.c prototypes (alphabetical) ***********************/
+
+unsigned long qh_clock (void);
+void   qh_checkflags (char *command, char *hiddenflags);
+void   qh_freebuffers (void);
+void    qh_freeqhull (boolT allmem);
+void    qh_init_A (FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]);
+void    qh_init_B (coordT *points, int numpoints, int dim, boolT ismalloc);
+void   qh_init_qhull_command (int argc, char *argv[]);
+void    qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
+void   qh_initflags (char *command);
+void   qh_initqhull_buffers (void);
+void   qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc);
+void    qh_initqhull_mem (void);
+void   qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile);
+void   qh_initthresholds (char *command);
+void    qh_option (char *option, int *i, realT *r);
+#if qh_QHpointer
+void   qh_restore_qhull (qhT **oldqh);
+qhT    *qh_save_qhull (void);
+#endif
+
+/***** -io.c prototypes (duplicated from io.h) ***********************/
+
+void    dfacet( unsigned id);
+void    dvertex( unsigned id);
+void   qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall);
+void   qh_produce_output(void);
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
+
+
+/********* -mem.c prototypes (duplicated from mem.h) **********************/
+
+void qh_meminit (FILE *ferr);
+void qh_memfreeshort (int *curlong, int *totlong);
+
+/********* -poly.c/poly2.c prototypes (duplicated from poly.h) **********************/
+
+void    qh_check_output (void);
+void    qh_check_points (void);
+setT   *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets);
+facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
+           realT *bestdist, boolT *isoutside);
+vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
+pointT *qh_point (int id);
+setT   *qh_pointfacet (void /*qh.facet_list*/);
+int     qh_pointid (pointT *point);
+setT   *qh_pointvertex (void /*qh.facet_list*/);
+void    qh_setvoronoi_all (void);
+void   qh_triangulate (void /*qh facet_list*/);
+
+/********* -stat.c prototypes (duplicated from stat.h) **********************/
+
+void    qh_collectstatistics (void);
+void    qh_printallstatistics (FILE *fp, char *string);
+
+#endif /* qhDEFqhull */
diff --git a/extern/qhull/include/qhull/qhull_a.h b/extern/qhull/include/qhull/qhull_a.h
new file mode 100755 (executable)
index 0000000..d4e69b0
--- /dev/null
@@ -0,0 +1,127 @@
+/*<html><pre>  -<a                             href="qh-qhull.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   qhull_a.h 
+   all header files for compiling qhull
+
+   see qh-qhull.htm
+
+   see qhull.h for user-level definitions
+   
+   see user.h for user-defineable constants
+   
+   defines internal functions for qhull.c global.c
+
+   copyright (c) 1993-2002, The Geometry Center
+
+   Notes:  grep for ((" and (" to catch fprintf("lkasdjf");
+           full parens around (x?y:z)
+          use '#include qhull/qhull_a.h' to avoid name clashes
+*/
+
+#ifndef qhDEFqhulla
+#define qhDEFqhulla
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>    /* some compilers will not need float.h */
+#include <limits.h>
+#include <time.h>
+#include <ctype.h>
+/*** uncomment here and qset.c
+     if string.h does not define memcpy()
+#include <memory.h>
+*/
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+#include "geom.h"
+#include "merge.h"
+#include "poly.h"
+#include "io.h"
+#include "stat.h"
+
+#if qh_CLOCKtype == 2  /* defined in user.h from qhull.h */
+#include <sys/types.h>
+#include <sys/times.h>
+#include <unistd.h>
+#endif
+
+#ifdef _MSC_VER  /* Microsoft Visual C++ */
+#pragma warning( disable : 4056)  /* float constant expression.  Looks like a compiler bug */
+#pragma warning( disable : 4146)  /* unary minus applied to unsigned type */
+#pragma warning( disable : 4244)  /* conversion from 'unsigned long' to 'real' */
+#pragma warning( disable : 4305)  /* conversion from 'const double' to 'float' */
+#endif
+
+/* ======= -macros- =========== */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="traceN">-</a>
+  
+  traceN((fp.ferr, "format\n", vars));  
+    calls fprintf if qh.IStracing >= N
+  
+  notes:
+    removing tracing reduces code size but doesn't change execution speed
+*/
+#ifndef qh_NOtrace
+#define trace0(args) {if (qh IStracing) fprintf args;}
+#define trace1(args) {if (qh IStracing >= 1) fprintf args;}
+#define trace2(args) {if (qh IStracing >= 2) fprintf args;}
+#define trace3(args) {if (qh IStracing >= 3) fprintf args;}
+#define trace4(args) {if (qh IStracing >= 4) fprintf args;}
+#define trace5(args) {if (qh IStracing >= 5) fprintf args;}
+#else /* qh_NOtrace */
+#define trace0(args) {}
+#define trace1(args) {}
+#define trace2(args) {}
+#define trace3(args) {}
+#define trace4(args) {}
+#define trace5(args) {}
+#endif /* qh_NOtrace */
+
+/***** -qhull.c prototypes (alphabetical after qhull) ********************/
+
+void   qh_qhull (void);
+boolT   qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist);
+void   qh_buildhull(void);
+void    qh_buildtracing (pointT *furthest, facetT *facet);
+void    qh_build_withrestart (void);
+void   qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet);
+void    qh_findhorizon(pointT *point, facetT *facet, int *goodvisible,int *goodhorizon);
+pointT *qh_nextfurthest (facetT **visible);
+void   qh_partitionall(setT *vertices, pointT *points,int npoints);
+void    qh_partitioncoplanar (pointT *point, facetT *facet, realT *dist);
+void    qh_partitionpoint (pointT *point, facetT *facet);
+void   qh_partitionvisible(boolT allpoints, int *numpoints);
+void    qh_precision (char *reason);
+void   qh_printsummary(FILE *fp);
+
+/***** -global.c internal prototypes (alphabetical) ***********************/
+
+void    qh_appendprint (qh_PRINT format);
+void   qh_freebuild (boolT allmem);
+void   qh_freebuffers (void);
+void    qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
+int     qh_strtol (const char *s, char **endp);
+double  qh_strtod (const char *s, char **endp);
+
+/***** -stat.c internal prototypes (alphabetical) ***********************/
+
+void   qh_allstatA (void);
+void   qh_allstatB (void);
+void   qh_allstatC (void);
+void   qh_allstatD (void);
+void   qh_allstatE (void);
+void   qh_allstatE2 (void);
+void   qh_allstatF (void);
+void   qh_allstatG (void);
+void   qh_allstatH (void);
+void   qh_freebuffers (void);
+void    qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
+
+#endif /* qhDEFqhulla */
diff --git a/extern/qhull/include/qhull/qset.h b/extern/qhull/include/qhull/qset.h
new file mode 100755 (executable)
index 0000000..6c0ff75
--- /dev/null
@@ -0,0 +1,468 @@
+/*<html><pre>  -<a                             href="qh-set.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   qset.h
+     header file for qset.c that implements set
+
+   see qh-set.htm and qset.c
+   
+   only uses mem.c, malloc/free
+
+   for error handling, writes message and calls
+      qh_errexit (qhmem_ERRqhull, NULL, NULL);
+   
+   set operations satisfy the following properties:
+    - sets have a max size, the actual size (if different) is stored at the end
+    - every set is NULL terminated
+    - sets may be sorted or unsorted, the caller must distinguish this
+   
+   copyright (c) 1993-2002, The Geometry Center
+*/
+
+#ifndef qhDEFset
+#define qhDEFset 1
+
+/*================= -structures- ===============*/
+
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT;   /* a set is a sorted or unsorted array of pointers */
+#endif
+
+/*-<a                                      href="qh-set.htm#TOC"
+>----------------------------------------</a><a name="setT">-</a>
+   
+setT
+  a set or list of pointers with maximum size and actual size.
+
+variations:
+  unsorted, unique   -- a list of unique pointers with NULL terminator
+                          user guarantees uniqueness
+  sorted            -- a sorted list of unique pointers with NULL terminator
+                          qset.c guarantees uniqueness
+  unsorted           -- a list of pointers terminated with NULL
+  indexed           -- an array of pointers with NULL elements 
+
+structure for set of n elements:
+
+       --------------
+       |  maxsize 
+       --------------
+       |  e[0] - a pointer, may be NULL for indexed sets
+       --------------
+       |  e[1]
+       
+       --------------
+       |  ...
+       --------------
+       |  e[n-1]
+       --------------
+       |  e[n] = NULL
+       --------------
+       |  ...
+       --------------
+       |  e[maxsize] - n+1 or NULL (determines actual size of set)
+       --------------
+
+*/
+
+/*-- setelemT -- internal type to allow both pointers and indices
+*/
+typedef union setelemT setelemT;
+union setelemT {
+  void    *p;
+  int      i;         /* integer used for e[maxSize] */
+};
+
+struct setT {
+  int maxsize;          /* maximum number of elements (except NULL) */
+  setelemT e[1];        /* array of pointers, tail is NULL */
+                        /* last slot (unless NULL) is actual size+1 
+                           e[maxsize]==NULL or e[e[maxsize]-1]==NULL */
+                        /* this may generate a warning since e[] contains
+                          maxsize elements */
+};
+
+/*=========== -constants- =========================*/
+
+/*-<a                                 href="qh-set.htm#TOC"
+  >-----------------------------------</a><a name="SETelemsize">-</a>
+   
+  SETelemsize
+    size of a set element in bytes
+*/
+#define SETelemsize sizeof(setelemT) 
+
+
+/*=========== -macros- =========================*/
+
+/*-<a                                 href="qh-set.htm#TOC"
+  >-----------------------------------</a><a name="FOREACHsetelement_">-</a>
+   
+   FOREACHsetelement_(type, set, variable)
+     define FOREACH iterator
+
+   declare:  
+     assumes *variable and **variablep are declared
+     no space in "variable)" [DEC Alpha cc compiler]
+
+   each iteration:
+     variable is set element
+     variablep is one beyond variable.  
+
+   to repeat an element:
+     variablep--; / *repeat* /
+
+   at exit:
+     variable is NULL at end of loop
+
+   example:  
+     #define FOREACHfacet_( facets ) FOREACHsetelement_( facetT, facets, facet )
+
+   notes:
+     use FOREACHsetelement_i_() if need index or include NULLs
+
+   WARNING: 
+     nested loops can't use the same variable (define another FOREACH)
+   
+     needs braces if nested inside another FOREACH
+     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
+*/
+#define FOREACHsetelement_(type, set, variable) \
+        if (((variable= NULL), set)) for(\
+          variable##p= (type **)&((set)->e[0].p); \
+         (variable= *variable##p++);)
+
+/*-<a                                      href="qh-set.htm#TOC"
+  >----------------------------------------</a><a name="FOREACHsetelement_i_">-</a>
+
+   FOREACHsetelement_i_(type, set, variable)
+     define indexed FOREACH iterator
+
+   declare:  
+     type *variable, variable_n, variable_i;
+
+   each iteration:
+     variable is set element, may be NULL
+     variable_i is index, variable_n is qh_setsize()
+
+   to repeat an element:
+     variable_i--; variable_n-- repeats for deleted element
+
+   at exit:
+     variable==NULL and variable_i==variable_n
+
+   example:
+     #define FOREACHfacet_i_( facets ) FOREACHsetelement_i_( facetT, facets, facet )
+   
+   WARNING: 
+     nested loops can't use the same variable (define another FOREACH)
+   
+     needs braces if nested inside another FOREACH
+     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
+*/
+#define FOREACHsetelement_i_(type, set, variable) \
+        if (((variable= NULL), set)) for (\
+          variable##_i= 0, variable= (type *)((set)->e[0].p), \
+                   variable##_n= qh_setsize(set);\
+          variable##_i < variable##_n;\
+          variable= (type *)((set)->e[++variable##_i].p) )
+
+/*-<a                                    href="qh-set.htm#TOC"
+  >--------------------------------------</a><a name="FOREACHsetelementreverse_">-</a>
+
+   FOREACHsetelementreverse_(type, set, variable)- 
+     define FOREACH iterator in reverse order
+
+   declare:  
+     assumes *variable and **variablep are declared
+     also declare 'int variabletemp'
+
+   each iteration:
+     variable is set element
+
+   to repeat an element:
+     variabletemp++; / *repeat* /
+
+   at exit:
+     variable is NULL
+
+   example:
+     #define FOREACHvertexreverse_( vertices ) FOREACHsetelementreverse_( vertexT, vertices, vertex )
+  
+   notes:
+     use FOREACHsetelementreverse12_() to reverse first two elements
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHsetelementreverse_(type, set, variable) \
+        if (((variable= NULL), set)) for(\
+          variable##temp= qh_setsize(set)-1, variable= qh_setlast(set);\
+          variable; variable= \
+          ((--variable##temp >= 0) ? SETelemt_(set, variable##temp, type) : NULL))
+
+/*-<a                                 href="qh-set.htm#TOC"
+  >-----------------------------------</a><a name="FOREACHsetelementreverse12_">-</a>
+
+   FOREACHsetelementreverse12_(type, set, variable)- 
+     define FOREACH iterator with e[1] and e[0] reversed
+
+   declare:  
+     assumes *variable and **variablep are declared
+
+   each iteration:
+     variable is set element
+     variablep is one after variable.  
+
+   to repeat an element:
+     variablep--; / *repeat* /
+
+   at exit:
+     variable is NULL at end of loop
+  
+   example
+     #define FOREACHvertexreverse12_( vertices ) FOREACHsetelementreverse12_( vertexT, vertices, vertex )
+
+   notes:
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHsetelementreverse12_(type, set, variable) \
+        if (((variable= NULL), set)) for(\
+          variable##p= (type **)&((set)->e[1].p); \
+         (variable= *variable##p); \
+          variable##p == ((type **)&((set)->e[0].p))?variable##p += 2: \
+             (variable##p == ((type **)&((set)->e[1].p))?variable##p--:variable##p++))
+
+/*-<a                                 href="qh-set.htm#TOC"
+  >-----------------------------------</a><a name="FOREACHelem_">-</a>
+
+   FOREACHelem_( set )- 
+     iterate elements in a set
+
+   declare:  
+     void *elem, *elemp;
+
+   each iteration:
+     elem is set element
+     elemp is one beyond
+
+   to repeat an element:
+     elemp--; / *repeat* /
+
+   at exit:
+     elem == NULL at end of loop
+  
+   example:
+     FOREACHelem_(set) {
+     
+   notes:
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHelem_(set) FOREACHsetelement_(void, set, elem)
+
+/*-<a                                 href="qh-set.htm#TOC"
+  >-----------------------------------</a><a name="FOREACHset_">-</a>
+
+   FOREACHset_( set )- 
+     iterate a set of sets
+
+   declare:  
+     setT *set, **setp;
+
+   each iteration:
+     set is set element
+     setp is one beyond
+
+   to repeat an element:
+     setp--; / *repeat* /
+
+   at exit:
+     set == NULL at end of loop
+  
+   example
+     FOREACHset_(sets) {
+     
+   notes:
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHset_(sets) FOREACHsetelement_(setT, sets, set)
+
+/*-<a                                       href="qh-set.htm#TOC"
+  >-----------------------------------------</a><a name="SETindex_">-</a>
+
+   SETindex_( set, elem )
+     return index of elem in set
+
+   notes:   
+     for use with FOREACH iteration
+
+   example:
+     i= SETindex_(ridges, ridge)
+*/
+#define SETindex_(set, elem) ((void **)elem##p - (void **)&(set)->e[1].p)
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETref_">-</a>
+
+   SETref_( elem )
+     l.h.s. for modifying the current element in a FOREACH iteration
+
+   example:
+     SETref_(ridge)= anotherridge;
+*/
+#define SETref_(elem) (elem##p[-1])
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETelem_">-</a>
+
+   SETelem_(set, n)
+     return the n'th element of set
+   
+   notes:
+      assumes that n is valid [0..size] and that set is defined
+      use SETelemt_() for type cast
+*/
+#define SETelem_(set, n)           ((set)->e[n].p)
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETelemt_">-</a>
+
+   SETelemt_(set, n, type)
+     return the n'th element of set as a type
+   
+   notes:
+      assumes that n is valid [0..size] and that set is defined
+*/
+#define SETelemt_(set, n, type)    ((type*)((set)->e[n].p))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETelemaddr_">-</a>
+
+   SETelemaddr_(set, n, type)
+     return address of the n'th element of a set
+   
+   notes:
+      assumes that n is valid [0..size] and set is defined 
+*/
+#define SETelemaddr_(set, n, type) ((type **)(&((set)->e[n].p)))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETfirst_">-</a>
+
+   SETfirst_(set)
+     return first element of set
+   
+*/
+#define SETfirst_(set)             ((set)->e[0].p)
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETfirstt_">-</a>
+
+   SETfirstt_(set, type)
+     return first element of set as a type
+   
+*/
+#define SETfirstt_(set, type)      ((type*)((set)->e[0].p))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETsecond_">-</a>
+
+   SETsecond_(set)
+     return second element of set
+   
+*/
+#define SETsecond_(set)            ((set)->e[1].p)
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETsecondt_">-</a>
+
+   SETsecondt_(set, type)
+     return second element of set as a type
+*/
+#define SETsecondt_(set, type)     ((type*)((set)->e[1].p))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETaddr_">-</a>
+
+   SETaddr_(set, type)
+       return address of set's elements
+*/
+#define SETaddr_(set,type)        ((type **)(&((set)->e[0].p)))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETreturnsize_">-</a>
+
+   SETreturnsize_(set, size) 
+     return size of a set
+   
+   notes:
+      set must be defined
+      use qh_setsize(set) unless speed is critical
+*/
+#define SETreturnsize_(set, size) (((size)= ((set)->e[(set)->maxsize].i))?(--(size)):((size)= (set)->maxsize))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETempty_">-</a>
+
+   SETempty_(set) 
+     return true (1) if set is empty
+   
+   notes:
+      set may be NULL
+*/
+#define SETempty_(set)                   (!set || (SETfirst_(set) ? 0:1))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETtruncate_">-</a>
+
+   SETtruncate_(set)
+     return first element of set
+
+   see:
+     qh_settruncate()
+   
+*/
+#define SETtruncate_(set, size) {set->e[set->maxsize].i= size+1; /* maybe overwritten */ \
+      set->e[size].p= NULL;}
+
+/*======= prototypes in alphabetical order ============*/
+
+void  qh_setaddsorted(setT **setp, void *elem);
+void  qh_setaddnth(setT **setp, int nth, void *newelem);
+void  qh_setappend(setT **setp, void *elem);
+void  qh_setappend_set(setT **setp, setT *setA);
+void  qh_setappend2ndlast(setT **setp, void *elem);
+void  qh_setcheck(setT *set, char *tname, int id);
+void  qh_setcompact(setT *set);
+setT *qh_setcopy(setT *set, int extra);
+void *qh_setdel(setT *set, void *elem);
+void *qh_setdellast(setT *set);
+void *qh_setdelnth(setT *set, int nth);
+void *qh_setdelnthsorted(setT *set, int nth);
+void *qh_setdelsorted(setT *set, void *newelem);
+setT *qh_setduplicate( setT *set, int elemsize);
+int   qh_setequal(setT *setA, setT *setB);
+int   qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB);
+int   qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB);
+void  qh_setfree(setT **set);
+void  qh_setfree2( setT **setp, int elemsize);
+void  qh_setfreelong(setT **set);
+int   qh_setin(setT *set, void *setelem);
+int   qh_setindex(setT *set, void *setelem);
+void  qh_setlarger(setT **setp);
+void *qh_setlast(setT *set);
+setT *qh_setnew(int size);
+setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend);
+void  qh_setprint(FILE *fp, char* string, setT *set);
+void  qh_setreplace(setT *set, void *oldelem, void *newelem);
+int   qh_setsize(setT *set);
+setT *qh_settemp(int setsize);
+void  qh_settempfree(setT **set);
+void  qh_settempfree_all(void);
+setT *qh_settemppop(void);
+void  qh_settemppush(setT *set);
+void  qh_settruncate (setT *set, int size);
+int   qh_setunique (setT **set, void *elem);
+void  qh_setzero (setT *set, int index, int size);
+
+
+#endif /* qhDEFset */
diff --git a/extern/qhull/include/qhull/stat.h b/extern/qhull/include/qhull/stat.h
new file mode 100755 (executable)
index 0000000..1dae54e
--- /dev/null
@@ -0,0 +1,520 @@
+  /*<html><pre>  -<a                             href="qh-stat.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   stat.h 
+     contains all statistics that are collected for qhull
+
+   see qh-stat.htm and stat.c
+
+   copyright (c) 1993-2002, The Geometry Center
+
+   recompile qhull if you change this file
+
+   Integer statistics are Z* while real statistics are W*.  
+
+   define maydebugx to call a routine at every statistic event
+
+*/
+
+#ifndef qhDEFstat
+#define qhDEFstat 1
+
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="KEEPstatistics">-</a>
+
+  qh_KEEPstatistics
+    0 turns off statistic gathering (except zzdef/zzinc/zzadd/zzval/wwval)
+*/
+#ifndef qh_KEEPstatistics
+#define qh_KEEPstatistics 1
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="statistics">-</a>
+
+  Zxxx for integers, Wxxx for reals
+
+  notes:
+    be sure that all statistics are defined in stat.c
+      otherwise initialization may core dump
+    can pick up all statistics by:
+      grep '[zw].*_[(][ZW]' *.c >z.x
+    remove trailers with query">-</a>
+    remove leaders with  query-replace-regexp [ ^I]+  (
+*/
+#if qh_KEEPstatistics
+enum statistics {     /* alphabetical after Z/W */
+    Zacoplanar,
+    Wacoplanarmax,
+    Wacoplanartot,
+    Zangle,
+    Wangle,
+    Wanglemax,
+    Wanglemin,
+    Zangletests,
+    Wareatot,
+    Wareamax,
+    Wareamin,
+    Zavoidold,
+    Wavoidoldmax,
+    Wavoidoldtot,
+    Zback0,
+    Zbestcentrum,
+    Zbestdist,
+    Zcentrumtests,
+    Zcheckpart,
+    Zcomputefurthest,
+    Zconcave,
+    Wconcavemax,
+    Wconcavetot,
+    Zconcaveridges,
+    Zconcaveridge,
+    Zcoplanar,
+    Wcoplanarmax,
+    Wcoplanartot,
+    Zcoplanarangle,
+    Zcoplanarcentrum,
+    Zcoplanarhorizon,
+    Zcoplanarinside,
+    Zcoplanarpart,
+    Zcoplanarridges,
+    Wcpu,
+    Zcyclefacetmax,
+    Zcyclefacettot,
+    Zcyclehorizon,
+    Zcyclevertex,
+    Zdegen,
+    Wdegenmax,
+    Wdegentot,
+    Zdegenvertex,
+    Zdelfacetdup, 
+    Zdelridge,
+    Zdelvertextot,
+    Zdelvertexmax,
+    Zdetsimplex,
+    Zdistcheck,
+    Zdistconvex,
+    Zdistgood,
+    Zdistio,
+    Zdistplane,
+    Zdiststat,
+    Zdistvertex,
+    Zdistzero,
+    Zdoc1,
+    Zdoc2,
+    Zdoc3,
+    Zdoc4,
+    Zdoc5,
+    Zdoc6,
+    Zdoc7,
+    Zdoc8,
+    Zdoc9,
+    Zdoc10,
+    Zdoc11,
+    Zdoc12,
+    Zdropdegen,
+    Zdropneighbor,
+    Zdupflip,
+    Zduplicate,
+    Wduplicatemax,
+    Wduplicatetot,
+    Zdupridge,
+    Zdupsame,
+    Zflipped, 
+    Wflippedmax, 
+    Wflippedtot, 
+    Zflippedfacets,
+    Zfindbest,
+    Zfindbestmax,
+    Zfindbesttot,
+    Zfindcoplanar,
+    Zfindfail,
+    Zfindhorizon,
+    Zfindhorizonmax,
+    Zfindhorizontot,
+    Zfindjump,
+    Zfindnew,
+    Zfindnewmax,
+    Zfindnewtot,
+    Zfindnewjump,
+    Zfindnewsharp,
+    Zgauss0,
+    Zgoodfacet,
+    Zhashlookup,
+    Zhashridge,
+    Zhashridgetest,
+    Zhashtests,
+    Zinsidevisible,
+    Zintersect,
+    Zintersectfail,
+    Zintersectmax,
+    Zintersectnum,
+    Zintersecttot,
+    Zmaxneighbors,
+    Wmaxout,
+    Wmaxoutside,
+    Zmaxridges,
+    Zmaxvertex,
+    Zmaxvertices,
+    Zmaxvneighbors,
+    Zmemfacets,
+    Zmempoints,
+    Zmemridges,
+    Zmemvertices,
+    Zmergeflipdup,
+    Zmergehorizon,
+    Zmergeinittot,
+    Zmergeinitmax,
+    Zmergeinittot2,
+    Zmergeintohorizon,
+    Zmergenew,
+    Zmergesettot,
+    Zmergesetmax,
+    Zmergesettot2,
+    Zmergesimplex,
+    Zmergevertex,
+    Wmindenom,
+    Wminvertex,
+    Zminnorm,
+    Zmultiridge,
+    Znearlysingular,
+    Zneighbor,
+    Wnewbalance,
+    Wnewbalance2,
+    Znewfacettot,
+    Znewfacetmax,
+    Znewvertex,
+    Wnewvertex,
+    Wnewvertexmax,
+    Znoarea,
+    Znonsimplicial,
+    Znowsimplicial,
+    Znotgood,
+    Znotgoodnew,
+    Znotmax,
+    Znumfacets,
+    Znummergemax,
+    Znummergetot,
+    Znumneighbors,
+    Znumridges,
+    Znumvertices,
+    Znumvisibility,
+    Znumvneighbors,
+    Zonehorizon,
+    Zpartangle,
+    Zpartcoplanar,
+    Zpartflip,
+    Zparthorizon,
+    Zpartinside,
+    Zpartition, 
+    Zpartitionall,
+    Zpartnear,
+    Zpbalance,
+    Wpbalance,
+    Wpbalance2, 
+    Zpostfacets, 
+    Zpremergetot,
+    Zprocessed,
+    Zremvertex,
+    Zremvertexdel,
+    Zrenameall,
+    Zrenamepinch,
+    Zrenameshare,
+    Zretry,
+    Wretrymax,
+    Zridge,
+    Wridge,
+    Wridgemax,
+    Zridge0,
+    Wridge0,
+    Wridge0max,
+    Zridgemid,
+    Wridgemid,
+    Wridgemidmax,
+    Zridgeok,
+    Wridgeok,
+    Wridgeokmax,
+    Zsearchpoints,
+    Zsetplane,
+    Ztestvneighbor,
+    Ztotcheck,
+    Ztothorizon,
+    Ztotmerge,
+    Ztotpartcoplanar,
+    Ztotpartition,
+    Ztotridges,
+    Ztotvertices,
+    Ztotvisible,
+    Ztricoplanar,
+    Ztricoplanarmax,
+    Ztricoplanartot,
+    Ztridegen,
+    Ztrimirror,
+    Ztrinull,
+    Wvertexmax,
+    Wvertexmin,
+    Zvertexridge,
+    Zvertexridgetot,
+    Zvertexridgemax,
+    Zvertices,
+    Zvisfacettot,
+    Zvisfacetmax,
+    Zvisvertextot,
+    Zvisvertexmax,
+    Zwidefacet,
+    Zwidevertices,
+    ZEND};
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="ZZstat">-</a>
+
+  Zxxx/Wxxx statistics that remain defined if qh_KEEPstatistics=0
+
+  notes:
+    be sure to use zzdef, zzinc, etc. with these statistics (no double checking!)
+*/
+#else
+enum statistics {     /* for zzdef etc. macros */
+  Zback0,
+  Zbestdist,
+  Zcentrumtests,
+  Zcheckpart,
+  Zconcaveridges,
+  Zcoplanarhorizon,
+  Zcoplanarpart,
+  Zcoplanarridges,
+  Zcyclefacettot,
+  Zcyclehorizon,
+  Zdelvertextot,
+  Zdistcheck,
+  Zdistconvex,
+  Zdistzero,
+  Zdoc1,
+  Zdoc2,
+  Zdoc3,
+  Zdoc11,
+  Zflippedfacets,
+  Zgauss0,
+  Zminnorm,
+  Zmultiridge,
+  Znearlysingular,
+  Wnewvertexmax,
+  Znumvisibility,
+  Zpartcoplanar,
+  Zpartition,
+  Zpartitionall,
+  Zprocessed,
+  Zretry,
+  Zridge,
+  Wridge,
+  Wridgemax,
+  Zridge0,
+  Wridge0,
+  Wridge0max,
+  Zridgemid,
+  Wridgemid,
+  Wridgemidmax,
+  Zridgeok,
+  Wridgeok,
+  Wridgeokmax,
+  Zsetplane,
+  Ztotmerge,
+    ZEND};
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="ztype">-</a>
+  
+  ztype
+    the type of a statistic sets its initial value.  
+
+  notes:
+    The type should be the same as the macro for collecting the statistic
+*/
+enum ztypes {zdoc,zinc,zadd,zmax,zmin,ZTYPEreal,wadd,wmax,wmin,ZTYPEend};
+
+/*========== macros and constants =============*/
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="MAYdebugx">-</a>
+  
+  MAYdebugx
+    define as maydebug() to be called frequently for error trapping
+*/
+#define MAYdebugx 
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="zdef_">-</a>
+  
+  zzdef_, zdef_( type, name, doc, -1)
+    define a statistic (assumes 'qhstat.next= 0;')
+
+  zdef_( type, name, doc, count)
+    define an averaged statistic
+    printed as name/count
+*/
+#define zzdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
+   qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
+#if qh_KEEPstatistics
+#define zdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
+   qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
+#else
+#define zdef_(type,name,doc,count)
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="zinc_">-</a>
+  
+  zzinc_( name ), zinc_( name)
+    increment an integer statistic
+*/
+#define zzinc_(id) {MAYdebugx; qhstat stats[id].i++;}
+#if qh_KEEPstatistics
+#define zinc_(id) {MAYdebugx; qhstat stats[id].i++;}
+#else
+#define zinc_(id) {}
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="zadd_">-</a>
+  
+  zzadd_( name, value ), zadd_( name, value ), wadd_( name, value )
+    add value to an integer or real statistic
+*/
+#define zzadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
+#define wwadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
+#if qh_KEEPstatistics
+#define zadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
+#define wadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
+#else
+#define zadd_(id, val) {}
+#define wadd_(id, val) {}
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="zval_">-</a>
+
+  zzval_( name ), zval_( name ), wwval_( name )
+    set or return value of a statistic
+*/
+#define zzval_(id) ((qhstat stats[id]).i)
+#define wwval_(id) ((qhstat stats[id]).r)
+#if qh_KEEPstatistics
+#define zval_(id) ((qhstat stats[id]).i)
+#define wval_(id) ((qhstat stats[id]).r)
+#else
+#define zval_(id) qhstat tempi
+#define wval_(id) qhstat tempr
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="zmax_">-</a>
+
+  zmax_( id, val ), wmax_( id, value )
+    maximize id with val
+*/
+#define wwmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
+#if qh_KEEPstatistics
+#define zmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].i,(val));}
+#define wmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
+#else
+#define zmax_(id, val) {}
+#define wmax_(id, val) {}
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="zmin_">-</a>
+
+  zmin_( id, val ), wmin_( id, value )
+    minimize id with val
+*/
+#if qh_KEEPstatistics
+#define zmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].i,(val));}
+#define wmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].r,(val));}
+#else
+#define zmin_(id, val) {}
+#define wmin_(id, val) {}
+#endif
+
+/*================== stat.h types ==============*/
+
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="intrealT">-</a>
+  intrealT
+    union of integer and real, used for statistics
+*/
+typedef union intrealT intrealT;    /* union of int and realT */
+union intrealT {
+    int i;
+    realT r;
+};
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="qhstat">-</a>
+  
+  qhstat
+    global data structure for statistics
+  
+  notes:
+   access to qh_qhstat is via the "qhstat" macro.  There are two choices
+   qh_QHpointer = 1     access globals via a pointer
+                        enables qh_saveqhull() and qh_restoreqhull()
+               = 0     qh_qhstat is a static data structure
+                       only one instance of qhull() can be active at a time
+                       default value
+   qh_QHpointer is defined in qhull.h
+
+   allocated in stat.c
+*/
+typedef struct qhstatT qhstatT; 
+#if qh_QHpointer
+#define qhstat qh_qhstat->
+extern qhstatT *qh_qhstat;
+#else
+#define qhstat qh_qhstat.
+extern qhstatT qh_qhstat; 
+#endif
+struct qhstatT {  
+  intrealT   stats[ZEND];     /* integer and real statistics */
+  unsigned   char id[ZEND+10]; /* id's in print order */
+  char      *doc[ZEND];       /* array of documentation strings */
+  short int  count[ZEND];     /* -1 if none, else index of count to use */
+  char       type[ZEND];      /* type, see ztypes above */
+  char       printed[ZEND];   /* true, if statistic has been printed */
+  intrealT   init[ZTYPEend];  /* initial values by types, set initstatistics */
+
+  int        next;            /* next index for zdef_ */
+  int        precision;       /* index for precision problems */
+  int        vridges;         /* index for Voronoi ridges */
+  int        tempi;
+  realT      tempr;
+};
+
+/*========== function prototypes ===========*/
+
+void    qh_allstatA(void);
+void    qh_allstatB(void);
+void    qh_allstatC(void);
+void    qh_allstatD(void);
+void    qh_allstatE(void);
+void    qh_allstatE2(void);
+void    qh_allstatF(void);
+void    qh_allstatG(void);
+void    qh_allstatH(void);
+void    qh_allstatI(void);
+void    qh_allstatistics (void);
+void    qh_collectstatistics (void);
+void   qh_freestatistics (void);
+void    qh_initstatistics (void);
+boolT  qh_newstats (int index, int *nextindex);
+boolT  qh_nostatistic (int i);
+void    qh_printallstatistics (FILE *fp, char *string);
+void    qh_printstatistics (FILE *fp, char *string);
+void   qh_printstatlevel (FILE *fp, int id, int start);
+void   qh_printstats (FILE *fp, int index, int *nextindex);
+realT   qh_stddev (int num, realT tot, realT tot2, realT *ave);
+
+#endif   /* qhDEFstat */
diff --git a/extern/qhull/include/qhull/user.h b/extern/qhull/include/qhull/user.h
new file mode 100755 (executable)
index 0000000..7955896
--- /dev/null
@@ -0,0 +1,762 @@
+/*<html><pre>  -<a                             href="qh-user.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   user.h
+   user redefinable constants
+
+   see qh-user.htm.  see COPYING for copyright information.
+
+   before reading any code, review qhull.h for data structure definitions and 
+   the "qh" macro.
+*/
+
+#ifndef qhDEFuser
+#define qhDEFuser 1
+
+/*============= data types and configuration macros ==========*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="realT">-</a>
+  
+  realT
+    set the size of floating point numbers
+  
+  qh_REALdigits 
+    maximimum number of significant digits
+  
+  qh_REAL_1, qh_REAL_2n, qh_REAL_3n
+    format strings for printf
+  
+  qh_REALmax, qh_REALmin
+    maximum and minimum (near zero) values  
+  
+  qh_REALepsilon
+    machine roundoff.  Maximum roundoff error for addition and multiplication.
+    
+  notes:
+   Select whether to store floating point numbers in single precision (float)
+   or double precision (double).
+   
+   Use 'float' to save about 8% in time and 25% in space.  This is particularly
+   help if high-d where convex hulls are space limited.  Using 'float' also
+   reduces the printed size of Qhull's output since numbers have 8 digits of 
+   precision.
+   
+   Use 'double' when greater arithmetic precision is needed.  This is needed
+   for Delaunay triangulations and Voronoi diagrams when you are not merging 
+   facets.
+
+   If 'double' gives insufficient precision, your data probably includes
+   degeneracies.  If so you should use facet merging (done by default)
+   or exact arithmetic (see imprecision section of manual, qh-impre.htm).  
+   You may also use option 'Po' to force output despite precision errors.
+
+   You may use 'long double', but many format statements need to be changed
+   and you may need a 'long double' square root routine.  S. Grundmann
+   (sg@eeiwzb.et.tu-dresden.de) has done this.  He reports that the code runs 
+   much slower with little gain in precision.    
+
+   WARNING: on some machines,    int f(){realT a= REALmax;return (a == REALmax);}
+      returns False.  Use (a > REALmax/2) instead of (a == REALmax).
+
+   REALfloat =   1      all numbers are 'float' type
+             =   0      all numbers are 'double' type
+*/
+#define REALfloat 0
+
+#if (REALfloat == 1)
+#define realT float
+#define REALmax FLT_MAX
+#define REALmin FLT_MIN
+#define REALepsilon FLT_EPSILON
+#define qh_REALdigits 8   /* maximum number of significant digits */
+#define qh_REAL_1 "%6.8g "
+#define qh_REAL_2n "%6.8g %6.8g\n"
+#define qh_REAL_3n "%6.8g %6.8g %6.8g\n"
+
+#elif (REALfloat == 0)
+#define realT double
+#define REALmax DBL_MAX
+#define REALmin DBL_MIN
+#define REALepsilon DBL_EPSILON
+#define qh_REALdigits 16    /* maximum number of significant digits */
+#define qh_REAL_1 "%6.16g "
+#define qh_REAL_2n "%6.16g %6.16g\n"
+#define qh_REAL_3n "%6.16g %6.16g %6.16g\n"
+
+#else
+#error unknown float option
+#endif
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="CPUclock">-</a>
+  
+  qh_CPUclock
+    define the clock() function for reporting the total time spent by Qhull
+    returns CPU ticks as a 'long int'
+    qh_CPUclock is only used for reporting the total time spent by Qhull
+
+  qh_SECticks 
+    the number of clock ticks per second
+
+  notes:
+    looks for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or assumes microseconds
+    to define a custom clock, set qh_CLOCKtype to 0
+
+    if your system does not use clock() to return CPU ticks, replace
+    qh_CPUclock with the corresponding function.  It is converted
+    to unsigned long to prevent wrap-around during long runs.
+   
+
+   Set qh_CLOCKtype to
+   
+     1         for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or microsecond
+                Note:  may fail if more than 1 hour elapsed time
+
+     2         use qh_clock() with POSIX times() (see global.c)
+*/
+#define qh_CLOCKtype 1  /* change to the desired number */
+
+#if (qh_CLOCKtype == 1)
+
+#if defined (CLOCKS_PER_SECOND)
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
+#define qh_SECticks CLOCKS_PER_SECOND
+
+#elif defined (CLOCKS_PER_SEC)
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
+#define qh_SECticks CLOCKS_PER_SEC
+
+#elif defined (CLK_TCK)
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
+#define qh_SECticks CLK_TCK
+
+#else
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
+#define qh_SECticks 1E6
+#endif
+
+#elif (qh_CLOCKtype == 2)
+#define qh_CPUclock    qh_clock()  /* return CPU clock */
+#define qh_SECticks 100
+
+#else /* qh_CLOCKtype == ? */
+#error unknown clock option
+#endif
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="RANDOM">-</a>
+  
+  qh_RANDOMtype, qh_RANDOMmax, qh_RANDOMseed
+    define random number generator
+
+    qh_RANDOMint generates a random integer between 0 and qh_RANDOMmax.  
+    qh_RANDOMseed sets the random number seed for qh_RANDOMint
+
+  Set qh_RANDOMtype (default 5) to:
+    1       for random() with 31 bits (UCB)
+    2       for rand() with RAND_MAX or 15 bits (system 5)
+    3       for rand() with 31 bits (Sun)
+    4       for lrand48() with 31 bits (Solaris)
+    5       for qh_rand() with 31 bits (included with Qhull)
+  
+  notes:
+    Random numbers are used by rbox to generate point sets.  Random
+    numbers are used by Qhull to rotate the input ('QRn' option),
+    simulate a randomized algorithm ('Qr' option), and to simulate
+    roundoff errors ('Rn' option).
+
+    Random number generators differ between systems.  Most systems provide
+    rand() but the period varies.  The period of rand() is not critical
+    since qhull does not normally use random numbers.  
+
+    The default generator is Park & Miller's minimal standard random
+    number generator [CACM 31:1195 '88].  It is included with Qhull.
+
+    If qh_RANDOMmax is wrong, qhull will report a warning and Geomview 
+    output will likely be invisible.
+*/
+#define qh_RANDOMtype 5   /* *** change to the desired number *** */
+
+#if (qh_RANDOMtype == 1)
+#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, random()/MAX */
+#define qh_RANDOMint random()
+#define qh_RANDOMseed_(seed) srandom(seed);
+
+#elif (qh_RANDOMtype == 2)
+#ifdef RAND_MAX
+#define qh_RANDOMmax ((realT)RAND_MAX)
+#else
+#define qh_RANDOMmax ((realT)32767)   /* 15 bits (System 5) */
+#endif
+#define qh_RANDOMint  rand()
+#define qh_RANDOMseed_(seed) srand((unsigned)seed);
+  
+#elif (qh_RANDOMtype == 3)
+#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, Sun */
+#define qh_RANDOMint  rand()
+#define qh_RANDOMseed_(seed) srand((unsigned)seed);
+
+#elif (qh_RANDOMtype == 4)
+#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, lrand38()/MAX */
+#define qh_RANDOMint lrand48()
+#define qh_RANDOMseed_(seed) srand48(seed);
+
+#elif (qh_RANDOMtype == 5)
+#define qh_RANDOMmax ((realT)2147483646UL)  /* 31 bits, qh_rand/MAX */
+#define qh_RANDOMint qh_rand()
+#define qh_RANDOMseed_(seed) qh_srand(seed);
+/* unlike rand(), never returns 0 */
+
+#else
+#error: unknown random option
+#endif
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="ORIENTclock">-</a>
+  
+  qh_ORIENTclock
+    0 for inward pointing normals by Geomview convention
+*/
+#define qh_ORIENTclock 0 
+
+
+/*========= performance related constants =========*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="HASHfactor">-</a>
+  
+  qh_HASHfactor
+    total hash slots / used hash slots.  Must be at least 1.1.
+      
+  notes:
+    =2 for at worst 50% occupancy for qh hash_table and normally 25% occupancy
+*/
+#define qh_HASHfactor 2
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="VERIFYdirect">-</a>
+  
+  qh_VERIFYdirect
+    with 'Tv' verify all points against all facets if op count is smaller
+
+  notes:
+    if greater, calls qh_check_bestdist() instead
+*/
+#define qh_VERIFYdirect 1000000 
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="INITIALsearch">-</a>
+  
+  qh_INITIALsearch
+     if qh_INITIALmax, search points up to this dimension
+*/
+#define qh_INITIALsearch 6
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="INITIALmax">-</a>
+  
+  qh_INITIALmax
+    if dim >= qh_INITIALmax, use min/max coordinate points for initial simplex
+      
+  notes:
+    from points with non-zero determinants
+    use option 'Qs' to override (much slower)
+*/
+#define qh_INITIALmax 8
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="JOGGLEdefault">-</a>
+  
+  qh_JOGGLEdefault
+    default qh.JOGGLEmax is qh.DISTround * qh_JOGGLEdefault
+
+  notes:
+    rbox s r 100 | qhull QJ1e-15 QR0 generates 90% faults at distround 7e-16
+    rbox s r 100 | qhull QJ1e-14 QR0 generates 70% faults
+    rbox s r 100 | qhull QJ1e-13 QR0 generates 35% faults
+    rbox s r 100 | qhull QJ1e-12 QR0 generates 8% faults
+    rbox s r 100 | qhull QJ1e-11 QR0 generates 1% faults
+    rbox s r 100 | qhull QJ1e-10 QR0 generates 0% faults
+    rbox 1000 W0 | qhull QJ1e-12 QR0 generates 86% faults
+    rbox 1000 W0 | qhull QJ1e-11 QR0 generates 20% faults
+    rbox 1000 W0 | qhull QJ1e-10 QR0 generates 2% faults
+    the later have about 20 points per facet, each of which may interfere
+
+    pick a value large enough to avoid retries on most inputs
+*/
+#define qh_JOGGLEdefault 30000.0
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="JOGGLEincrease">-</a>
+  
+  qh_JOGGLEincrease
+    factor to increase qh.JOGGLEmax on qh_JOGGLEretry or qh_JOGGLEagain
+*/
+#define qh_JOGGLEincrease 10.0
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="JOGGLEretry">-</a>
+  
+  qh_JOGGLEretry
+    if ZZretry = qh_JOGGLEretry, increase qh.JOGGLEmax
+
+  notes:
+    try twice at the original value in case of bad luck the first time
+*/
+#define qh_JOGGLEretry 2
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="JOGGLEagain">-</a>
+  
+  qh_JOGGLEagain
+    every following qh_JOGGLEagain, increase qh.JOGGLEmax
+
+  notes:
+    1 is OK since it's already failed qh_JOGGLEretry times
+*/
+#define qh_JOGGLEagain 1
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="JOGGLEmaxincrease">-</a>
+  
+  qh_JOGGLEmaxincrease
+    maximum qh.JOGGLEmax due to qh_JOGGLEincrease
+    relative to qh.MAXwidth
+
+  notes:
+    qh.joggleinput will retry at this value until qh_JOGGLEmaxretry
+*/
+#define qh_JOGGLEmaxincrease 1e-2
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="JOGGLEmaxretry">-</a>
+  
+  qh_JOGGLEmaxretry
+    stop after qh_JOGGLEmaxretry attempts
+*/
+#define qh_JOGGLEmaxretry 100
+
+/*========= memory constants =========*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MEMalign">-</a>
+  
+  qh_MEMalign
+    memory alignment for qh_meminitbuffers() in global.c
+    
+  notes:
+    to avoid bus errors, memory allocation must consider alignment requirements.
+    malloc() automatically takes care of alignment.   Since mem.c manages
+    its own memory, we need to explicitly specify alignment in
+    qh_meminitbuffers().
+
+    A safe choice is sizeof(double).  sizeof(float) may be used if doubles 
+    do not occur in data structures and pointers are the same size.  Be careful
+    of machines (e.g., DEC Alpha) with large pointers. 
+
+    If using gcc, best alignment is
+              #define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *))
+*/
+#define qh_MEMalign fmax_(sizeof(realT), sizeof(void *))
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MEMbufsize">-</a>
+  
+  qh_MEMbufsize
+    size of additional memory buffers
+    
+  notes:
+    used for qh_meminitbuffers() in global.c
+*/
+#define qh_MEMbufsize 0x10000       /* allocate 64K memory buffers */
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MEMinitbuf">-</a>
+  
+  qh_MEMinitbuf
+    size of initial memory buffer
+    
+  notes:
+    use for qh_meminitbuffers() in global.c
+*/
+#define qh_MEMinitbuf 0x20000      /* initially allocate 128K buffer */
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="INFINITE">-</a>
+  
+  qh_INFINITE
+    on output, indicates Voronoi center at infinity
+*/
+#define qh_INFINITE  -10.101
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="DEFAULTbox">-</a>
+  
+  qh_DEFAULTbox
+    default box size (Geomview expects 0.5)
+*/
+#define qh_DEFAULTbox 0.5 
+
+/*======= conditional compilation ============================*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="compiler">-</a>
+
+  __cplusplus
+    defined by C++ compilers
+
+  __MSC_VER
+    defined by Microsoft Visual C++
+  
+  __MWERKS__ && __POWERPC__
+    defined by Metrowerks when compiling for the Power Macintosh
+
+  __STDC__
+    defined for strict ANSI C 
+*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="COMPUTEfurthest">-</a>
+  qh_COMPUTEfurthest 
+    compute furthest distance to an outside point instead of storing it with the facet
+    =1 to compute furthest
+  
+  notes:
+    computing furthest saves memory but costs time
+      about 40% more distance tests for partitioning
+      removes facet->furthestdist 
+*/
+#define qh_COMPUTEfurthest 0
+                         
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="KEEPstatistics">-</a>
+  qh_KEEPstatistics   
+    =0 removes most of statistic gathering and reporting
+
+  notes:
+    if 0, code size is reduced by about 4%.
+*/
+#define qh_KEEPstatistics 1
+                       
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MAXoutside">-</a>
+  qh_MAXoutside 
+    record outer plane for each facet
+    =1 to record facet->maxoutside
+  
+  notes:
+    this takes a realT per facet and slightly slows down qhull
+    it produces better outer planes for geomview output 
+*/
+#define qh_MAXoutside 1
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="NOmerge">-</a>
+  qh_NOmerge
+    disables facet merging if defined
+    
+  notes:
+    This saves about 10% space.
+    
+    Unless 'Q0'
+      qh_NOmerge sets 'QJ' to avoid precision errors
+
+    #define qh_NOmerge    
+
+  see:
+    <a href="mem.h#NOmem">qh_NOmem</a> in mem.c
+    
+    see user.c/user_eg.c for removing io.o
+*/  
+    
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="NOtrace">-</a>
+  qh_NOtrace
+    no tracing if defined 
+  
+  notes:
+    This saves about 5% space.
+
+    #define qh_NOtrace
+*/    
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="QHpointer">-</a>
+  
+  qh_QHpointer
+    access global data with pointer or static structure
+
+  qh_QHpointer  = 1     access globals via a pointer to allocated memory
+                        enables qh_saveqhull() and qh_restoreqhull()
+                       costs about 8% in time and 2% in space
+
+               = 0     qh_qh and qh_qhstat are static data structures
+                       only one instance of qhull() can be active at a time
+                       default value
+
+  notes:
+    all global variables for qhull are in qh, qhmem, and qhstat
+    qh is defined in qhull.h
+    qhmem is defined in mem.h
+    qhstat is defined in stat.h
+
+  see:
+    user_eg.c for an example
+*/
+#define qh_QHpointer 0
+#if 0  /* sample code */
+    qhT *oldqhA, *oldqhB;
+
+    exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
+                      flags, outfile, errfile); 
+    /* use results from first call to qh_new_qhull */
+    oldqhA= qh_save_qhull();
+    exitcode= qh_new_qhull (dimB, numpointsB, pointsB, ismalloc,
+                      flags, outfile, errfile); 
+    /* use results from second call to qh_new_qhull */
+    oldqhB= qh_save_qhull();
+    qh_restore_qhull (&oldqhA);
+    /* use results from first call to qh_new_qhull */
+    qh_freeqhull (qh_ALL);  /* frees all memory used by first call */
+    qh_restore_qhull (&oldqhB);
+    /* use results from second call to qh_new_qhull */
+    qh_freeqhull (!qh_ALL); /* frees long memory used by second call */
+    qh_memfreeshort (&curlong, &totlong);  /* frees short memory and memory allocator */
+#endif
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="QUICKhelp">-</a>
+  qh_QUICKhelp        
+    =1 to use abbreviated help messages, e.g., for degenerate inputs
+*/
+#define qh_QUICKhelp    0  
+
+/* ============ -merge constants- ====================
+
+   These constants effect facet merging.  You probably will not need
+   to modify these.  They effect the performance of facet merging.
+*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="DIMmergeVertex">-</a>
+  
+  qh_DIMmergeVertex
+    max dimension for vertex merging (it is not effective in high-d)
+*/
+#define qh_DIMmergeVertex 6
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="DIMreduceBuild">-</a>
+  
+  qh_DIMreduceBuild
+     max dimension for vertex reduction during build (slow in high-d)
+*/
+#define qh_DIMreduceBuild 5
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="BESTcentrum">-</a>
+     
+  qh_BESTcentrum
+     if > 2*dim+n vertices, qh_findbestneighbor() tests centrums (faster)
+     else, qh_findbestneighbor() tests all vertices (much better merges)
+
+  qh_BESTcentrum2
+     if qh_BESTcentrum2 * DIM3 + BESTcentrum < #vertices tests centrums
+*/
+#define qh_BESTcentrum 20
+#define qh_BESTcentrum2 2
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="BESTnonconvex">-</a>
+  
+  qh_BESTnonconvex
+    if > dim+n neighbors, qh_findbestneighbor() tests nonconvex ridges.
+    
+  notes:
+    It is needed because qh_findbestneighbor is slow for large facets
+*/
+#define qh_BESTnonconvex 15 
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MAXnewmerges">-</a>
+  
+  qh_MAXnewmerges
+    if >n newmerges, qh_merge_nonconvex() calls qh_reducevertices_centrums.
+     
+  notes:
+    It is needed because postmerge can merge many facets at once
+*/
+#define qh_MAXnewmerges 2
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MAXnewcentrum">-</a>
+  
+  qh_MAXnewcentrum
+    if <= dim+n vertices (n approximates the number of merges),
+      reset the centrum in qh_updatetested() and qh_mergecycle_facets()
+    
+  notes:
+    needed to reduce cost and because centrums may move too much if 
+    many vertices in high-d
+*/
+#define qh_MAXnewcentrum 5
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="COPLANARratio">-</a>
+  
+  qh_COPLANARratio
+    for 3-d+ merging, qh.MINvisible is n*premerge_centrum
+
+  notes:
+    for non-merging, it's DISTround
+*/
+#define qh_COPLANARratio 3
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="DISToutside">-</a>
+  
+  qh_DISToutside
+    When is a point clearly outside of a facet?  
+    Stops search in qh_findbestnew or qh_partitionall
+    qh_findbest uses qh.MINoutside since since it is only called if no merges.
+     
+  notes:
+    'Qf' always searches for best facet
+    if !qh.MERGING, same as qh.MINoutside. 
+    if qh_USEfindbestnew, increase value since neighboring facets may be ill-behaved
+      [Note: Zdelvertextot occurs normally with interior points]
+            RBOX 1000 s Z1 G1e-13 t1001188774 | QHULL Tv
+    When there is a sharp edge, need to move points to a
+    clearly good facet; otherwise may be lost in another partitioning.
+    if too big then O(n^2) behavior for partitioning in cone
+    if very small then important points not processed
+    Needed in qh_partitionall for
+      RBOX 1000 s Z1 G1e-13 t1001032651 | QHULL Tv
+    Needed in qh_findbestnew for many instances of
+      RBOX 1000 s Z1 G1e-13 t | QHULL Tv
+
+  See:  
+    qh_DISToutside -- when is a point clearly outside of a facet
+    qh_SEARCHdist -- when is facet coplanar with the best facet?
+    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_DISToutside ((qh_USEfindbestnew ? 2 : 1) * \
+     fmax_((qh MERGING ? 2 : 1)*qh MINoutside, qh max_outside))
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="RATIOnearinside">-</a>
+  
+  qh_RATIOnearinside
+    ratio of qh.NEARinside to qh.ONEmerge for retaining inside points for
+    qh_check_maxout().  
+  
+  notes:
+    This is overkill since do not know the correct value.
+    It effects whether 'Qc' reports all coplanar points
+    Not used for 'd' since non-extreme points are coplanar
+*/
+#define qh_RATIOnearinside 5
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="SEARCHdist">-</a>
+  
+  qh_SEARCHdist
+    When is a facet coplanar with the best facet?  
+    qh_findbesthorizon: all coplanar facets of the best facet need to be searched.
+
+  See:
+    qh_DISToutside -- when is a point clearly outside of a facet
+    qh_SEARCHdist -- when is facet coplanar with the best facet?
+    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_SEARCHdist ((qh_USEfindbestnew ? 2 : 1) * \
+      (qh max_outside + 2 * qh DISTround + fmax_( qh MINvisible, qh MAXcoplanar)));
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="USEfindbestnew">-</a>
+  
+  qh_USEfindbestnew
+     Always use qh_findbestnew for qh_partitionpoint, otherwise use
+     qh_findbestnew if merged new facet or sharpnewfacets.
+  
+  See:
+    qh_DISToutside -- when is a point clearly outside of a facet
+    qh_SEARCHdist -- when is facet coplanar with the best facet?
+    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_USEfindbestnew (zzval_(Ztotmerge) > 50)
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="WIDEcoplanar">-</a>
+  
+  qh_WIDEcoplanar
+    n*MAXcoplanar or n*MINvisible for a WIDEfacet 
+    
+    if vertex is further than qh.WIDEfacet from the hyperplane
+    then its ridges are not counted in computing the area, and
+    the facet's centrum is frozen. 
+    
+  notes:
+   qh.WIDEfacet= max(qh.MAXoutside,qh_WIDEcoplanar*qh.MAXcoplanar,
+      qh_WIDEcoplanar * qh.MINvisible);
+*/
+#define qh_WIDEcoplanar 6
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MAXnarrow">-</a>
+  
+  qh_MAXnarrow
+    max. cosine in initial hull that sets qh.NARROWhull
+       
+  notes:
+    If qh.NARROWhull, the initial partition does not make 
+    coplanar points.  If narrow, a coplanar point can be 
+    coplanar to two facets of opposite orientations and
+    distant from the exact convex hull.
+
+    Conservative estimate.  Don't actually see problems until it is -1.0
+*/
+#define qh_MAXnarrow -0.99999999
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="WARNnarrow">-</a>
+  
+  qh_WARNnarrow
+    max. cosine in initial hull to warn about qh.NARROWhull
+      
+  notes:
+    this is a conservative estimate.  
+    Don't actually see problems until it is -1.0.  See qh-impre.htm
+*/
+#define qh_WARNnarrow -0.999999999999999
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="ZEROdelaunay">-</a>
+  
+  qh_ZEROdelaunay
+    a zero Delaunay facet occurs for input sites coplanar with their convex hull
+    the last normal coefficient of a zero Delaunay facet is within
+        qh_ZEROdelaunay * qh.ANGLEround of 0
+      
+  notes:
+    qh_ZEROdelaunay does not allow for joggled input ('QJ').
+
+    You can avoid zero Delaunay facets by surrounding the input with a box.
+
+    Use option 'PDk:-n' to explicitly define zero Delaunay facets
+      k= dimension of input sites (e.g., 3 for 3-d Delaunay triangulation)
+      n= the cutoff for zero Delaunay facets (e.g., 'PD3:-1e-12')
+*/
+#define qh_ZEROdelaunay 2
+
+#endif /* qh_DEFuser */
+
+
+
diff --git a/extern/qhull/src/Make-config.sh b/extern/qhull/src/Make-config.sh
new file mode 100755 (executable)
index 0000000..90bbb95
--- /dev/null
@@ -0,0 +1,285 @@
+#!/bin/sh -e
+#
+# Make-config.sh
+#
+#     Setup for Debian build
+#
+#     Writes configure.in and Makefile.am files
+#     and runs automake and autoconfig
+#
+#     Use 'make dist' to build Unix distribution.
+#     Use 'configure; make' to build Qhull
+#
+#note:
+#     'configure; make' does not work under cygwin.
+#      src/unix.c:354: variable 'qh_qh' can't be auto-imported.
+#      Please read the documentation for ld's --enable-auto-import for details.
+
+###################################################
+###########  ../configure.in ######################
+###################################################
+
+echo Create ../configure.in
+cat >../configure.in <<\HERE-CONFIGURE
+dnl configure.in for the qhull package
+dnl Author: Rafael Laboissiere <rafael@debian.org>
+dnl Created: Mon Dec  3 21:36:21 CET 2001
+
+AC_INIT(src/qhull.c)
+AM_INIT_AUTOMAKE(qhull, 2002.1)
+
+AC_PROG_CC
+AC_PROG_LIBTOOL
+
+AC_OUTPUT([Makefile src/Makefile html/Makefile eg/Makefile])
+
+HERE-CONFIGURE
+
+###################################################
+###########  ../Makefile.am #######################
+###################################################
+
+echo Create ../Makefile.am
+cat >../Makefile.am <<\HERE-TOP
+### Makefile.am for the qhull package (main)
+### Author: Rafael Laboissiere <rafael@debian.org>
+### Created: Mon Dec  3 21:36:21 CET 2001
+
+### Documentation files
+
+# to:
+docdir = $(prefix)/share/doc/$(PACKAGE)
+
+# which:
+doc_DATA = \
+  Announce.txt \
+  COPYING.txt \
+  README.txt \
+  REGISTER.txt
+
+### Extra files to be included in the tarball
+
+EXTRA_DIST = \
+  $(doc_DATA) \
+  File_id.diz \
+  QHULL-GO.pif
+
+### Subdirectories for Automaking
+
+SUBDIRS = src html eg
+
+HERE-TOP
+
+###################################################
+###########  ../eg/Makefile.am ####################
+###################################################
+
+echo Create ../eg/Makefile.am
+cat >../eg/Makefile.am <<\HERE-AM
+### Makefile.am for the qhull package (eg)
+### Author: Rafael Laboissiere <rafael@debian.org>
+### Created: Mon Dec  3 21:36:21 CET 2001
+
+### Documentation files
+
+# to:
+docdir = $(prefix)/share/doc/$(PACKAGE)
+examplesdir = $(docdir)/examples
+
+# which:
+examples_DATA = \
+  q_eg \
+  q_egtest \
+  q_test \
+  Qhull-go.bat \
+  q_test.bat
+
+### Extra files to be included in the tarball
+
+EXTRA_DIST = $(examples_DATA)
+
+HERE-AM
+
+###################################################
+###########  ../html/Makefile.am ##################
+###################################################
+
+echo Create ../html/Makefile.am
+cat >../html/Makefile.am <<\HERE-HTML
+### Makefile.am for the qhull package (html)
+### Author: Rafael Laboissiere <rafael@debian.org>
+### Created: Mon Dec  3 21:36:21 CET 2001
+
+### Man pages (trick to get around .man extension)
+
+%.1: %.man
+       cp $< $@
+CLEANFILES = *.1
+man_MANS = rbox.1 qhull.1
+
+### Documentation files
+
+# to:
+docdir = $(prefix)/share/doc/$(PACKAGE)
+htmldir = $(docdir)/html
+
+# which:
+html_DATA = \
+  index.htm \
+  qconvex.htm \
+  qdelau_f.htm \
+  qdelaun.htm \
+  qh--4d.gif \
+  qh--cone.gif \
+  qh--dt.gif \
+  qh--geom.gif \
+  qh--half.gif \
+  qh--rand.gif \
+  qh-eg.htm \
+  qh-faq.htm \
+  qh-get.htm \
+  qh-home.htm \
+  qh-impre.htm \
+  qh-in.htm \
+  qh-optc.htm \
+  qh-optf.htm \
+  qh-optg.htm \
+  qh-opto.htm \
+  qh-optp.htm \
+  qh-optq.htm \
+  qh-optt.htm \
+  qh-quick.htm \
+  qhalf.htm \
+  qhull.htm \
+  qvoron_f.htm \
+  qvoronoi.htm \
+  rbox.htm
+
+### Extra files to be included in the tarball
+
+EXTRA_DIST = \
+  $(html_DATA) \
+  qhull.man \
+  qhull.txt \
+  rbox.man \
+  rbox.txt
+
+HERE-HTML
+
+###################################################
+###########  ../src/Makefile.am ###################
+###################################################
+
+echo Create ../src/Makefile.am
+cat >../src/Makefile.am <<\HERE-SRC
+### Makefile.am for the qhull package (src)
+### Author: Rafael Laboissiere <rafael@debian.org>
+### Created: Mon Dec  3 21:36:21 CET 2001
+
+### Shared Library
+
+# to:
+lib_LTLIBRARIES = libqhull.la
+
+# from:
+libqhull_la_SOURCES = \
+  user.c \
+  global.c \
+  stat.c \
+  io.c \
+  geom2.c \
+  poly2.c \
+  merge.c \
+  qhull.c \
+  geom.c \
+  poly.c \
+  qset.c \
+  mem.c
+
+# how:
+libqhull_la_LDFLAGS = -version-info 0:0:0 -lm
+
+### Utility programs
+
+# to:
+bin_PROGRAMS = qhull rbox qconvex qdelaunay qvoronoi qhalf
+
+# from:
+qhull_SOURCES = unix.c
+rbox_SOURCES = rbox.c
+qconvex_SOURCES = qconvex.c
+qdelaunay_SOURCES = qdelaun.c
+qvoronoi_SOURCES = qvoronoi.c
+qhalf_SOURCES = qhalf.c
+
+# how:
+qhull_LDADD = libqhull.la
+rbox_LDADD = libqhull.la
+qconvex_LDADD = libqhull.la
+qdelaunay_LDADD = libqhull.la
+qvoronoi_LDADD = libqhull.la
+qhalf_LDADD = libqhull.la
+
+### Include files
+
+pkginclude_HEADERS = \
+  geom.h \
+  mem.h \
+  poly.h \
+  qhull_a.h \
+  stat.h \
+  io.h \
+  merge.h \
+  qhull.h  \
+  qset.h \
+  user.h
+
+
+### Example programs
+
+# to:
+docdir = $(prefix)/share/doc/$(PACKAGE)
+examplesdir = $(docdir)/examples
+
+# which:
+examples_DATA = \
+  user_eg.c \
+  user_eg2.c \
+  qhull_interface.cpp \
+  Makefile.txt \
+  Make-config.sh \
+  MBorland
+
+doc_DATA = Changes.txt \
+    index.htm \
+    qh-geom.htm \
+    qh-globa.htm \
+    qh-io.htm \
+    qh-mem.htm \
+    qh-merge.htm \
+    qh-poly.htm \
+    qh-qhull.htm \
+    qh-set.htm \
+    qh-stat.htm \
+    qh-user.htm
+
+
+### Extra files to be included in the tarball
+
+EXTRA_DIST = \
+  $(doc_DATA) \
+  $(examples_DATA)
+
+HERE-SRC
+
+###################################################
+###########  run automake autoconf ################
+###################################################
+
+
+echo Run automake, libtoolize, and autoconf
+cd ..; aclocal &&\
+  automake --foreign --add-missing --force-missing && \
+  libtoolize --force && \
+  autoconf
+
diff --git a/extern/qhull/src/Makefile.txt b/extern/qhull/src/Makefile.txt
new file mode 100755 (executable)
index 0000000..e87b66b
--- /dev/null
@@ -0,0 +1,190 @@
+# Unix Makefile for qhull and rbox
+#
+#       see README.txt
+#
+#       make           to produce qhull qconvex qdelaunay qhalf qvoronoi rbox
+#       make qvoronoi  to produce qvoronoi (etc.)
+#       make qhullx    to produce qhull qconvex etc.  w/o using libqhull.a
+#       make doc       to print documentation
+#       make install   to copy qhull, rbox, qhull.1, rbox.1 to BINDIR, MANDIR
+#       make new       to rebuild qhull and rbox from source
+#
+#       make printall  to print all files
+#       make user_eg   to produce user_eg
+#       make user_eg2  to produce user_eg2
+#       make clean     to remove object files and core
+#       make cleanall  to remove all generated files
+#
+#       PRINTMAN --  command for printing manual pages
+#       PRINTC --  command for printing C files
+#       BINDIR -- directory where to copy executables
+#       MANDIR -- directory where to copy manual pages
+#       CC --     ANSI C or C++ compiler
+#       CCOPTS1 - options used to compile .c files
+#       CCOPTS2 -- options used to link .o files
+#
+#       CFILES -- .c files for printing
+#       HFILES -- .h files for printing
+#       DFILES -- documentation files
+#       MFILES -- man pages and html files
+#       TFILES -- .txt versions of html html files
+#       FILES -- all other files
+#       OBJS -- specifies the object files of libqhull.a
+#
+BINDIR  = /usr/local/bin
+MANDIR  = /usr/local/man/man1
+
+# if you do not have enscript, try a2ps or just use lpr.  The files are text.
+PRINTMAN = enscript -2rl
+PRINTC = enscript -2r
+# PRINTMAN = lpr
+# PRINTC = lpr
+
+#for Gnu's gcc compiler -O2 for optimization, -g for debugging, -Wall for check
+#
+CC     = gcc
+CCOPTS1 = -O2 -ansi 
+
+# for Sun's cc compiler, -fast or O2 for optimization, -g for debugging, -Xc for ANSI
+#CC = cc
+#CCOPTS1 = -Xc -v -fast
+
+# for Silicon Graphics cc compiler, -O2 for optimization, -g for debugging
+#CC = cc
+#CCOPTS1 = -ansi -O2
+
+# for Next cc compiler with fat executable
+#CC = cc
+#CCOPTS1 = -ansi -O2 -arch m68k -arch i386 -arch hppa
+
+# for loader, ld
+CCOPTS2 = $(CCOPTS1)
+
+# OBJS in execution frequency order.  CFILES after qhull.c are alphabetical
+OBJS = user.o global.o stat.o io.o geom2.o poly2.o \
+       merge.o qhull.o geom.o poly.o qset.o mem.o
+
+CFILES= unix.c qhull.c geom.c geom2.c global.c io.c mem.c merge.c poly.c \
+        poly2.c qset.c stat.c user.c qconvex.c qdelaun.c qhalf.c qvoronoi.c
+HFILES= user.h qhull.h qhull_a.h geom.h io.h mem.h merge.h poly.h qset.h stat.h
+TXTFILES= ../Announce.txt ../REGISTER.txt ../COPYING.txt ../README.txt Changes.txt
+DOCFILES= ../html/rbox.txt ../html/qhull.txt
+FILES=  Makefile rbox.c user_eg.c ../eg/q_test ../eg/q_egtest ../eg/q_eg
+HTMFILES= qhull.man rbox.man qh-in.htm qh-optg.htm qh-optt.htm qh-optp.htm \
+        index.htm qh-quick.htm qh-impre.htm qh-eg.htm \
+        qh-optc.htm qh-opto.htm qh-optf.htm qh-optq.htm \
+           qh-c.htm qh-faq.htm qhull.htm qconvex.htm qdelaun.htm \
+               qh-geom.htm qh-globa.htm qh-io.htm qh-mem.htm qh-merge.htm \
+               qh-poly.htm qh-qhull.htm qh-set.htm qh-stat.htm qh-user.htm \
+               qdelau_f.htm qhalf.htm qvoronoi.htm qvoron_f.htm rbox.htm 
+
+all: rbox qconvex qdelaunay qhalf qvoronoi qhull
+
+unix.o:   qhull.h user.h mem.h
+qconvex.o:   qhull.h user.h mem.h
+qdelaun.o:   qhull.h user.h mem.h
+qhalf.o:   qhull.h user.h mem.h
+qvoronoi.o:   qhull.h user.h mem.h
+qhull.o:  $(HFILES)
+geom.o:   $(HFILES)
+geom2.o:  $(HFILES)
+global.o: $(HFILES)
+io.o:     $(HFILES)
+mem.o:    mem.h 
+merge.o:  $(HFILES)
+poly.o:   $(HFILES)
+poly2.o:  $(HFILES)
+qset.o:   qset.h mem.h 
+stat.o:   $(HFILES)
+user.o:   $(HFILES)
+
+.c.o:
+       $(CC) -c $(CCOPTS1) $<
+
+clean:
+       rm -f *.o ../core qconvex qdelaunay qhalf qvoronoi qhull libqhull.a \
+           *.exe
+
+cleanall: clean
+       rm -f *~ ../rbox ../qhull ../qhalf ../qconvex ../qdelaunay ../qhalf\
+          ../qvoronoi ../user_eg ../user_eg2 ../*.exe >/dev/null
+
+doc: 
+       $(PRINTMAN) $(TXTFILES) $(DOCFILES)
+
+install: all 
+       cp ../qconvex $(BINDIR)/qconvex
+       cp ../qdelaunay $(BINDIR)/qdelaunay
+       cp ../qhalf $(BINDIR)/qhalf
+       cp ../qhull $(BINDIR)/qhull
+       cp ../qvoronoi $(BINDIR)/qvoronoi
+       cp ../rbox $(BINDIR)/rbox
+       cp ../html/qhull.man $(MANDIR)/qhull.1
+       cp ../html/rbox.man $(MANDIR)/rbox.1
+
+new:    cleanall all
+
+printall: doc printh printc printf
+
+printh:
+       $(PRINTC) $(HFILES)
+
+printc:
+       $(PRINTC) $(CFILES)
+
+printf:
+       $(PRINTC) $(FILES) 
+
+libqhull.a: $(OBJS)
+       @echo if 'ar' or 'ranlib' fails, try 'make qhullx'
+       ar r libqhull.a $(OBJS)
+       @echo the next line may need to be removed.
+       -test -x /bin/ranlib -o -x /usr/bin/ranlib && ranlib libqhull.a
+
+# don't use ../qconvex.  Does not work on Red Hat Linux
+qconvex: qconvex.o libqhull.a
+       $(CC) -o qconvex $(CCOPTS2) qconvex.o -L. -lqhull -lm 
+       cp qconvex ..
+
+qdelaunay: qdelaun.o libqhull.a
+       $(CC) -o qdelaunay $(CCOPTS2) qdelaun.o -L. -lqhull -lm 
+       cp qdelaunay ..
+
+qhalf: qhalf.o libqhull.a
+       $(CC) -o qhalf $(CCOPTS2) qhalf.o -L. -lqhull -lm 
+       cp qhalf ..
+
+qvoronoi: qvoronoi.o libqhull.a
+       $(CC) -o qvoronoi $(CCOPTS2) qvoronoi.o -L. -lqhull -lm 
+       cp qvoronoi ..
+
+qhull: unix.o libqhull.a
+       $(CC) -o qhull $(CCOPTS2) unix.o -L. -lqhull -lm 
+       cp qhull ..
+       -chmod +x ../eg/q_test ../eg/q_eg ../eg/q_egtest
+       -cd ..; ./rbox D4 | ./qhull
+
+# compile qhull without using libqhull.a
+qhullx: qconvex.o qdelaun.o qhalf.o qvoronoi.o unix.o $(OBJS)
+       $(CC) -o qconvex $(CCOPTS2) qconvex.o $(OBJS) -lm 
+       $(CC) -o qdelaunay $(CCOPTS2) qdelaun.o $(OBJS) -lm 
+       $(CC) -o qhalf $(CCOPTS2) qhalf.o $(OBJS) -lm 
+       $(CC) -o qvoronoi $(CCOPTS2) qvoronoi.o $(OBJS) -lm 
+       $(CC) -o qhull $(CCOPTS2) unix.o $(OBJS) -lm 
+       cp qconvex qdelaunay qhalf qvoronoi qhull ..
+       -chmod +x ../eg/q_test ../eg/q_eg ../eg/q_egtest
+       -cd ..; ./rbox D4 | ./qhull
+
+rbox: rbox.o
+       $(CC) -o rbox rbox.o $(CCOPTS2) -lm
+       cp rbox ..
+
+user_eg: user_eg.o libqhull.a 
+       $(CC)  -o user_eg $(CCOPTS2) user_eg.o  -L. -lqhull -lm 
+       cp user_eg ..
+
+user_eg2: user_eg2.o libqhull.a 
+       $(CC)  -o user_eg2 $(CCOPTS2) user_eg2.o  -L. -lqhull -lm 
+       cp user_eg2 ..
+
+# end of Makefile
diff --git a/extern/qhull/src/geom.c b/extern/qhull/src/geom.c
new file mode 100755 (executable)
index 0000000..b3cf198
--- /dev/null
@@ -0,0 +1,1230 @@
+/*<html><pre>  -<a                             href="qh-geom.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   geom.c 
+   geometric routines of qhull
+
+   see qh-geom.htm and geom.h
+
+   copyright (c) 1993-2002 The Geometry Center        
+
+   infrequent code goes into geom2.c
+*/
+   
+#include "qhull_a.h"
+   
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="distplane">-</a>
+  
+  qh_distplane( point, facet, dist )
+    return distance from point to facet
+
+  returns:
+    dist
+    if qh.RANDOMdist, joggles result
+  
+  notes:  
+    dist > 0 if point is above facet (i.e., outside)
+    does not error (for sortfacets)
+    
+  see:
+    qh_distnorm in geom2.c
+*/
+void qh_distplane (pointT *point, facetT *facet, realT *dist) {
+  coordT *normal= facet->normal, *coordp, randr;
+  int k;
+  
+  switch(qh hull_dim){
+  case 2:
+    *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1];
+    break;
+  case 3:
+    *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2];
+    break;
+  case 4:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3];
+    break;
+  case 5:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4];
+    break;
+  case 6:
+    *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];
+    break;
+  case 7:  
+    *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];
+    break;
+  case 8:
+    *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];
+    break;
+  default:
+    *dist= facet->offset;
+    coordp= point;
+    for (k= qh hull_dim; k--; )
+      *dist += *coordp++ * *normal++;
+    break;
+  }
+  zinc_(Zdistplane);
+  if (!qh RANDOMdist && qh IStracing < 4)
+    return;
+  if (qh RANDOMdist) {
+    randr= qh_RANDOMint;
+    *dist += (2.0 * randr / qh_RANDOMmax - 1.0) *
+      qh RANDOMfactor * qh MAXabs_coord;
+  }
+  if (qh IStracing >= 4) {
+    fprintf (qh ferr, "qh_distplane: ");
+    fprintf (qh ferr, qh_REAL_1, *dist);
+    fprintf (qh ferr, "from p%d to f%d\n", qh_pointid(point), facet->id);
+  }
+  return;
+} /* distplane */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="findbest">-</a>
+  
+  qh_findbest( point, startfacet, bestoutside, qh_ISnewfacets, qh_NOupper, dist, isoutside, numpart )
+    find facet that is furthest below a point 
+    for upperDelaunay facets
+      returns facet only if !qh_NOupper and clearly above
+
+  input:
+    starts search at 'startfacet' (can not be flipped)
+    if !bestoutside (qh_ALL), stops at qh.MINoutside
+
+  returns:
+    best facet (reports error if NULL)
+    early out if isoutside defined and bestdist > qh.MINoutside
+    dist is distance to facet
+    isoutside is true if point is outside of facet
+    numpart counts the number of distance tests
+
+  see also:
+    qh_findbestnew()
+    
+  notes:
+    If merging (testhorizon), searches horizon facets of coplanar best facets because
+    after qh_distplane, this and qh_partitionpoint are the most expensive in 3-d
+      avoid calls to distplane, function calls, and real number operations.
+    caller traces result
+    Optimized for outside points.   Tried recording a search set for qh_findhorizon.
+    Made code more complicated.
+
+  when called by qh_partitionvisible():
+    indicated by qh_ISnewfacets
+    qh.newfacet_list is list of simplicial, new facets
+    qh_findbestnew set if qh_sharpnewfacets returns True (to use qh_findbestnew)
+    qh.bestfacet_notsharp set if qh_sharpnewfacets returns False
+
+  when called by qh_findfacet(), qh_partitionpoint(), qh_partitioncoplanar(), 
+                 qh_check_bestdist(), qh_addpoint()
+    indicated by !qh_ISnewfacets
+    returns best facet in neighborhood of given facet
+      this is best facet overall if dist > -   qh.MAXcoplanar 
+        or hull has at least a "spherical" curvature
+
+  design:
+    initialize and test for early exit
+    repeat while there are better facets
+      for each neighbor of facet
+        exit if outside facet found
+       test for better facet
+    if point is inside and partitioning
+      test for new facets with a "sharp" intersection
+      if so, future calls go to qh_findbestnew()
+    test horizon facets
+*/
+facetT *qh_findbest (pointT *point, facetT *startfacet, 
+                    boolT bestoutside, boolT isnewfacets, boolT noupper,
+                    realT *dist, boolT *isoutside, int *numpart) {
+  realT bestdist= -REALmax/2 /* avoid underflow */;
+  facetT *facet, *neighbor, **neighborp, *bestfacet= NULL;
+  facetT *bestfacet_all= startfacet;
+  int oldtrace= qh IStracing;
+  unsigned int visitid= ++qh visit_id;
+  int numpartnew=0;
+  boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
+
+  zinc_(Zfindbest);
+  if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid (point))) {
+    if (qh TRACElevel > qh IStracing)
+      qh IStracing= qh TRACElevel;
+    fprintf (qh ferr, "qh_findbest: point p%d starting at f%d isnewfacets? %d, unless %d exit if > %2.2g\n",
+            qh_pointid(point), startfacet->id, isnewfacets, bestoutside, qh MINoutside);
+    fprintf(qh ferr, "  testhorizon? %d noupper? %d", testhorizon, noupper);
+    fprintf (qh ferr, "  Last point added was p%d.", qh furthest_id);
+    fprintf(qh ferr, "  Last merge was #%d.  max_outside %2.2g\n", zzval_(Ztotmerge), qh max_outside);
+  }
+  if (isoutside)
+    *isoutside= True;
+  if (!startfacet->flipped) {  /* test startfacet */
+    *numpart= 1;
+    qh_distplane (point, startfacet, dist);  /* this code is duplicated below */
+    if (!bestoutside && *dist >= qh MINoutside 
+    && (!startfacet->upperdelaunay || !noupper)) {
+      bestfacet= startfacet;
+      goto LABELreturn_best;
+    }
+    bestdist= *dist;
+    if (!startfacet->upperdelaunay) {
+      bestfacet= startfacet;
+    } 
+  }else 
+    *numpart= 0;
+  startfacet->visitid= visitid;
+  facet= startfacet;
+  while (facet) {
+    trace4((qh ferr, "qh_findbest: neighbors of f%d, bestdist %2.2g f%d\n", 
+                facet->id, bestdist, getid_(bestfacet)));
+    FOREACHneighbor_(facet) {
+      if (!neighbor->newfacet && isnewfacets)
+        continue;
+      if (neighbor->visitid == visitid)
+       continue;
+      neighbor->visitid= visitid;
+      if (!neighbor->flipped) {  /* code duplicated above */
+       (*numpart)++;
+       qh_distplane (point, neighbor, dist);
+       if (*dist > bestdist) {
+         if (!bestoutside && *dist >= qh MINoutside 
+         && (!neighbor->upperdelaunay || !noupper)) {
+           bestfacet= neighbor;
+           goto LABELreturn_best;
+         }
+         if (!neighbor->upperdelaunay) {
+           bestfacet= neighbor;
+           bestdist= *dist;
+         }
+         break; /* switch to neighor */
+       } /* end of *dist>bestdist */
+      } /* end of !flipped */
+    } /* end of FOREACHneighbor */
+    facet= neighbor;  /* non-NULL only if *dist>bestdist */
+  } /* end of while facet (directed search) */
+  if (isnewfacets) { 
+    if (!bestfacet) {
+      bestdist= -REALmax/2; 
+      bestfacet= qh_findbestnew (point, startfacet->next, &bestdist, bestoutside, isoutside, &numpartnew);
+      testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
+    }else if (!qh findbest_notsharp && bestdist < - qh DISTround) {
+      if (qh_sharpnewfacets()) { 
+       /* seldom used, qh_findbestnew will retest all facets */
+       zinc_(Zfindnewsharp);
+       bestfacet= qh_findbestnew (point, bestfacet, &bestdist, bestoutside, isoutside, &numpartnew);
+       testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
+       qh findbestnew= True;
+      }else
+       qh findbest_notsharp= True;
+    }
+  }
+  if (!bestfacet) {
+    fprintf(qh ferr, "\n\
+qh_findbest: all neighbors of facet %d are flipped or upper Delaunay.\n\
+Please report this error to qhull_bug@geom.umn.edu with the input and all of the output.\n",
+       startfacet->id);
+    qh_errexit (qh_ERRqhull, startfacet, NULL);
+  }
+  if (testhorizon) 
+    bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, bestfacet, noupper, &bestdist, &numpartnew);
+  *dist= bestdist;
+  if (isoutside && bestdist < qh MINoutside)
+    *isoutside= False;
+LABELreturn_best:
+  zadd_(Zfindbesttot, *numpart);
+  zmax_(Zfindbestmax, *numpart);
+  (*numpart) += numpartnew;
+  qh IStracing= oldtrace;
+  return bestfacet;
+}  /* findbest */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="findbesthorizon">-</a>
+  
+  qh_findbesthorizon( qh_IScheckmax, point, startfacet, qh_NOupper, &bestdist, &numpart )
+    search coplanar and better horizon facets from startfacet/bestdist
+    ischeckmax turns off statistics and minsearch update
+    all arguments must be initialized
+  returns (ischeckmax):
+    best facet
+  returns (!ischeckmax):
+    best facet that is not upperdelaunay
+    allows upperdelaunay that is clearly outside
+  returns:
+    bestdist is distance to bestfacet
+    numpart -- updates number of distance tests
+
+  notes:
+    no early out -- use qh_findbest() or qh_findbestnew()
+    Searches coplanar or better horizon facets
+
+  when called by qh_check_maxout() (qh_IScheckmax)
+    startfacet must be closest to the point
+      Otherwise, if point is beyond and below startfacet, startfacet may be a local minimum
+      even though other facets are below the point.
+    updates facet->maxoutside for good, visited facets
+    may return NULL
+
+    searchdist is qh.max_outside + 2 * DISTround
+      + max( MINvisible('Vn'), MAXcoplanar('Un'));
+    This setting is a guess.  It must be at least max_outside + 2*DISTround 
+    because a facet may have a geometric neighbor across a vertex
+
+  design:
+    for each horizon facet of coplanar best facets
+      continue if clearly inside
+      unless upperdelaunay or clearly outside
+         update best facet
+*/
+facetT *qh_findbesthorizon (boolT ischeckmax, pointT* point, facetT *startfacet, boolT noupper, realT *bestdist, int *numpart) {
+  facetT *bestfacet= startfacet;
+  realT dist;
+  facetT *neighbor, **neighborp, *facet;
+  facetT *nextfacet= NULL; /* optimize last facet of coplanarset */
+  int numpartinit= *numpart, coplanarset_size;
+  unsigned int visitid= ++qh visit_id;
+  boolT newbest= False; /* for tracing */
+  realT minsearch, searchdist;  /* skip facets that are too far from point */
+
+  if (!ischeckmax) {
+    zinc_(Zfindhorizon);
+  }else {
+#if qh_MAXoutside
+    if ((!qh ONLYgood || startfacet->good) && *bestdist > startfacet->maxoutside)
+      startfacet->maxoutside= *bestdist;
+#endif
+  }
+  searchdist= qh_SEARCHdist; /* multiple of qh.max_outside and precision constants */
+  minsearch= *bestdist - searchdist;
+  if (ischeckmax) {
+    /* Always check coplanar facets.  Needed for RBOX 1000 s Z1 G1e-13 t996564279 | QHULL Tv */
+    minimize_(minsearch, -searchdist);
+  }
+  coplanarset_size= 0;
+  facet= startfacet;
+  while (True) {
+    trace4((qh ferr, "qh_findbesthorizon: neighbors of f%d bestdist %2.2g f%d ischeckmax? %d noupper? %d minsearch %2.2g searchdist %2.2g\n", 
+               facet->id, *bestdist, getid_(bestfacet), ischeckmax, noupper,
+               minsearch, searchdist));
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == visitid) 
+       continue;
+      neighbor->visitid= visitid;
+      if (!neighbor->flipped) { 
+       qh_distplane (point, neighbor, &dist);
+       (*numpart)++;
+       if (dist > *bestdist) {
+         if (!neighbor->upperdelaunay || ischeckmax || (!noupper && dist >= qh MINoutside)) {
+           bestfacet= neighbor;
+           *bestdist= dist;
+           newbest= True;
+           if (!ischeckmax) {
+             minsearch= dist - searchdist;
+             if (dist > *bestdist + searchdist) {
+               zinc_(Zfindjump);  /* everything in qh.coplanarset at least searchdist below */
+               coplanarset_size= 0;
+             }
+           }
+         }
+       }else if (dist < minsearch) 
+         continue;  /* if ischeckmax, dist can't be positive */
+#if qh_MAXoutside
+       if (ischeckmax && dist > neighbor->maxoutside)
+         neighbor->maxoutside= dist;
+#endif      
+      } /* end of !flipped */
+      if (nextfacet) {
+       if (!coplanarset_size++) {
+         SETfirst_(qh coplanarset)= nextfacet;
+         SETtruncate_(qh coplanarset, 1);
+       }else
+         qh_setappend (&qh coplanarset, nextfacet); /* Was needed for RBOX 1000 s W1e-13 P0 t996547055 | QHULL d Qbb Qc Tv
+                                                and RBOX 1000 s Z1 G1e-13 t996564279 | qhull Tv  */
+      }
+      nextfacet= neighbor;
+    } /* end of EACHneighbor */
+    facet= nextfacet;
+    if (facet) 
+      nextfacet= NULL;
+    else if (!coplanarset_size)
+      break; 
+    else if (!--coplanarset_size) {
+      facet= SETfirst_(qh coplanarset);
+      SETtruncate_(qh coplanarset, 0);
+    }else
+      facet= (facetT*)qh_setdellast (qh coplanarset);
+  } /* while True, for each facet in qh.coplanarset */
+  if (!ischeckmax) {
+    zadd_(Zfindhorizontot, *numpart - numpartinit);
+    zmax_(Zfindhorizonmax, *numpart - numpartinit);
+    if (newbest)
+      zinc_(Zparthorizon);
+  }
+  trace4((qh ferr, "qh_findbesthorizon: newbest? %d bestfacet f%d bestdist %2.2g\n", newbest, getid_(bestfacet), *bestdist));
+  return bestfacet;
+}  /* findbesthorizon */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="findbestnew">-</a>
+  
+  qh_findbestnew( point, startfacet, dist, isoutside, numpart )
+    find best newfacet for point
+    searches all of qh.newfacet_list starting at startfacet
+    searches horizon facets of coplanar best newfacets
+    searches all facets if startfacet == qh.facet_list
+  returns:
+    best new or horizon facet that is not upperdelaunay
+    early out if isoutside and not 'Qf'
+    dist is distance to facet
+    isoutside is true if point is outside of facet
+    numpart is number of distance tests
+
+  notes:
+    Always used for merged new facets (see qh_USEfindbestnew)
+    Avoids upperdelaunay facet unless (isoutside and outside)
+
+    Uses qh.visit_id, qh.coplanarset.  
+    If share visit_id with qh_findbest, coplanarset is incorrect.
+
+    If merging (testhorizon), searches horizon facets of coplanar best facets because
+    a point maybe coplanar to the bestfacet, below its horizon facet,
+    and above a horizon facet of a coplanar newfacet.  For example,
+      rbox 1000 s Z1 G1e-13 | qhull
+      rbox 1000 s W1e-13 P0 t992110337 | QHULL d Qbb Qc
+
+    qh_findbestnew() used if
+       qh_sharpnewfacets -- newfacets contains a sharp angle
+       if many merges, qh_premerge found a merge, or 'Qf' (qh.findbestnew)
+
+  see also:
+    qh_partitionall() and qh_findbest()
+
+  design:
+    for each new facet starting from startfacet
+      test distance from point to facet
+      return facet if clearly outside
+      unless upperdelaunay and a lowerdelaunay exists
+         update best facet
+    test horizon facets
+*/
+facetT *qh_findbestnew (pointT *point, facetT *startfacet,
+          realT *dist, boolT bestoutside, boolT *isoutside, int *numpart) {
+  realT bestdist= -REALmax/2, minsearch= -REALmax/2;
+  facetT *bestfacet= NULL, *facet;
+  int oldtrace= qh IStracing, i;
+  unsigned int visitid= ++qh visit_id;
+  realT distoutside= 0.0;
+  boolT isdistoutside; /* True if distoutside is defined */
+  boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
+
+  if (!startfacet) {
+    if (qh MERGING)
+      fprintf(qh ferr, "qhull precision error (qh_findbestnew): merging has formed and deleted a cone of new facets.  Can not continue.\n");
+    else
+      fprintf(qh ferr, "qhull internal error (qh_findbestnew): no new facets for point p%d\n",
+             qh furthest_id);      
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  zinc_(Zfindnew);
+  if (qh BESToutside || bestoutside)
+    isdistoutside= False;
+  else {
+    isdistoutside= True;
+    distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
+  }
+  if (isoutside)
+    *isoutside= True;
+  *numpart= 0;
+  if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid (point))) {
+    if (qh TRACElevel > qh IStracing)
+      qh IStracing= qh TRACElevel;
+    fprintf(qh ferr, "qh_findbestnew: point p%d facet f%d. Stop? %d if dist > %2.2g\n",
+            qh_pointid(point), startfacet->id, isdistoutside, distoutside);
+    fprintf(qh ferr, "  Last point added p%d visitid %d.",  qh furthest_id, visitid);
+    fprintf(qh ferr, "  Last merge was #%d.\n", zzval_(Ztotmerge));
+  }
+  /* visit all new facets starting with startfacet, maybe qh facet_list */
+  for (i= 0, facet= startfacet; i < 2; i++, facet= qh newfacet_list) {
+    FORALLfacet_(facet) {
+      if (facet == startfacet && i)
+       break;
+      facet->visitid= visitid;
+      if (!facet->flipped) {
+       qh_distplane (point, facet, dist);
+       (*numpart)++;
+       if (*dist > bestdist) {
+         if (!facet->upperdelaunay || *dist >= qh MINoutside) {
+           bestfacet= facet;
+           if (isdistoutside && *dist >= distoutside)
+             goto LABELreturn_bestnew;
+           bestdist= *dist;
+         }
+       }
+      } /* end of !flipped */
+    } /* FORALLfacet from startfacet or qh newfacet_list */
+  }
+  if (testhorizon || !bestfacet)
+    bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, bestfacet ? bestfacet : startfacet, 
+                                       !qh_NOupper, &bestdist, numpart);  
+  *dist= bestdist;
+  if (isoutside && *dist < qh MINoutside)
+    *isoutside= False;
+LABELreturn_bestnew:
+  zadd_(Zfindnewtot, *numpart);
+  zmax_(Zfindnewmax, *numpart);
+  trace4((qh ferr, "qh_findbestnew: bestfacet f%d bestdist %2.2g\n", getid_(bestfacet), *dist));
+  qh IStracing= oldtrace;
+  return bestfacet;
+}  /* findbestnew */
+
+/* ============ hyperplane functions -- keep code together [?] ============ */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="backnormal">-</a>
+  
+  qh_backnormal( rows, numrow, numcol, sign, normal, nearzero )
+    given an upper-triangular rows array and a sign,
+    solve for normal equation x using back substitution over rows U
+
+  returns:
+     normal= x
+      
+     if will not be able to divzero() when normalized (qh.MINdenom_2 and qh.MINdenom_1_2),
+       if fails on last row
+         this means that the hyperplane intersects [0,..,1]
+         sets last coordinate of normal to sign
+       otherwise
+         sets tail of normal to [...,sign,0,...], i.e., solves for b= [0...0]
+         sets nearzero
+
+  notes:
+     assumes numrow == numcol-1
+
+     see Golub & van Loan 4.4-9 for back substitution
+
+     solves Ux=b where Ax=b and PA=LU
+     b= [0,...,0,sign or 0]  (sign is either -1 or +1)
+     last row of A= [0,...,0,1]
+
+     1) Ly=Pb == y=b since P only permutes the 0's of   b
+     
+  design:
+    for each row from end
+      perform back substitution
+      if near zero
+        use qh_divzero for division
+        if zero divide and not last row
+          set tail of normal to 0
+*/
+void qh_backnormal (realT **rows, int numrow, int numcol, boolT sign,
+       coordT *normal, boolT *nearzero) {
+  int i, j;
+  coordT *normalp, *normal_tail, *ai, *ak;
+  realT diagonal;
+  boolT waszero;
+  int zerocol= -1;
+  
+  normalp= normal + numcol - 1;
+  *normalp--= (sign ? -1.0 : 1.0);
+  for(i= numrow; i--; ) {
+    *normalp= 0.0;
+    ai= rows[i] + i + 1;
+    ak= normalp+1;
+    for(j= i+1; j < numcol; j++)
+      *normalp -= *ai++ * *ak++;
+    diagonal= (rows[i])[i];
+    if (fabs_(diagonal) > qh MINdenom_2)
+      *(normalp--) /= diagonal;
+    else {
+      waszero= False;
+      *normalp= qh_divzero (*normalp, diagonal, qh MINdenom_1_2, &waszero);
+      if (waszero) {
+        zerocol= i;
+       *(normalp--)= (sign ? -1.0 : 1.0);
+       for (normal_tail= normalp+2; normal_tail < normal + numcol; normal_tail++)
+         *normal_tail= 0.0;
+      }else
+       normalp--;
+    }
+  }
+  if (zerocol != -1) {
+    zzinc_(Zback0);
+    *nearzero= True;
+    trace4((qh ferr, "qh_backnormal: zero diagonal at column %d.\n", i));
+    qh_precision ("zero diagonal on back substitution");
+  }
+} /* backnormal */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="gausselim">-</a>
+  
+  qh_gausselim( rows, numrow, numcol, sign )
+    Gaussian elimination with partial pivoting
+
+  returns:
+    rows is upper triangular (includes row exchanges)
+    flips sign for each row exchange
+    sets nearzero if pivot[k] < qh.NEARzero[k], else clears it
+
+  notes:
+    if nearzero, the determinant's sign may be incorrect.
+    assumes numrow <= numcol
+
+  design:
+    for each row
+      determine pivot and exchange rows if necessary
+      test for near zero
+      perform gaussian elimination step
+*/
+void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero) {
+  realT *ai, *ak, *rowp, *pivotrow;
+  realT n, pivot, pivot_abs= 0.0, temp;
+  int i, j, k, pivoti, flip=0;
+  
+  *nearzero= False;
+  for(k= 0; k < numrow; k++) {
+    pivot_abs= fabs_((rows[k])[k]);
+    pivoti= k;
+    for(i= k+1; i < numrow; i++) {
+      if ((temp= fabs_((rows[i])[k])) > pivot_abs) {
+       pivot_abs= temp;
+       pivoti= i;
+      }
+    }
+    if (pivoti != k) {
+      rowp= rows[pivoti]; 
+      rows[pivoti]= rows[k]; 
+      rows[k]= rowp; 
+      *sign ^= 1;
+      flip ^= 1;
+    }
+    if (pivot_abs <= qh NEARzero[k]) {
+      *nearzero= True;
+      if (pivot_abs == 0.0) {   /* remainder of column == 0 */
+       if (qh IStracing >= 4) {
+         fprintf (qh ferr, "qh_gausselim: 0 pivot at column %d. (%2.2g < %2.2g)\n", k, pivot_abs, qh DISTround);
+         qh_printmatrix (qh ferr, "Matrix:", rows, numrow, numcol);
+       }
+       zzinc_(Zgauss0);
+        qh_precision ("zero pivot for Gaussian elimination");
+       goto LABELnextcol;
+      }
+    }
+    pivotrow= rows[k] + k;
+    pivot= *pivotrow++;  /* signed value of pivot, and remainder of row */
+    for(i= k+1; i < numrow; i++) {
+      ai= rows[i] + k;
+      ak= pivotrow;
+      n= (*ai++)/pivot;   /* divzero() not needed since |pivot| >= |*ai| */
+      for(j= numcol - (k+1); j--; )
+       *ai++ -= n * *ak++;
+    }
+  LABELnextcol:
+    ;
+  }
+  wmin_(Wmindenom, pivot_abs);  /* last pivot element */
+  if (qh IStracing >= 5)
+    qh_printmatrix (qh ferr, "qh_gausselem: result", rows, numrow, numcol);
+} /* gausselim */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="getangle">-</a>
+  
+  qh_getangle( vect1, vect2 )
+    returns the dot product of two vectors
+    if qh.RANDOMdist, joggles result
+
+  notes:
+    the angle may be > 1.0 or < -1.0 because of roundoff errors
+
+*/
+realT qh_getangle(pointT *vect1, pointT *vect2) {
+  realT angle= 0, randr;
+  int k;
+
+  for(k= qh hull_dim; k--; )
+    angle += *vect1++ * *vect2++;
+  if (qh RANDOMdist) {
+    randr= qh_RANDOMint;
+    angle += (2.0 * randr / qh_RANDOMmax - 1.0) *
+      qh RANDOMfactor;
+  }
+  trace4((qh ferr, "qh_getangle: %2.2g\n", angle));
+  return(angle);
+} /* getangle */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="getcenter">-</a>
+  
+  qh_getcenter( vertices )
+    returns arithmetic center of a set of vertices as a new point
+
+  notes:
+    allocates point array for center
+*/
+pointT *qh_getcenter(setT *vertices) {
+  int k;
+  pointT *center, *coord;
+  vertexT *vertex, **vertexp;
+  int count= qh_setsize(vertices);
+
+  if (count < 2) {
+    fprintf (qh ferr, "qhull internal error (qh_getcenter): not defined for %d points\n", count);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  center= (pointT *)qh_memalloc(qh normal_size);
+  for (k=0; k < qh hull_dim; k++) {
+    coord= center+k;
+    *coord= 0.0;
+    FOREACHvertex_(vertices)
+      *coord += vertex->point[k];
+    *coord /= count;
+  }
+  return(center);
+} /* getcenter */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="getcentrum">-</a>
+  
+  qh_getcentrum( facet )
+    returns the centrum for a facet as a new point
+
+  notes:
+    allocates the centrum
+*/
+pointT *qh_getcentrum(facetT *facet) {
+  realT dist;
+  pointT *centrum, *point;
+
+  point= qh_getcenter(facet->vertices);
+  zzinc_(Zcentrumtests);
+  qh_distplane (point, facet, &dist);
+  centrum= qh_projectpoint(point, facet, dist);
+  qh_memfree(point, qh normal_size);
+  trace4((qh ferr, "qh_getcentrum: for f%d, %d vertices dist= %2.2g\n",
+         facet->id, qh_setsize(facet->vertices), dist));
+  return centrum;
+} /* getcentrum */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="getdistance">-</a>
+  
+  qh_getdistance( facet, neighbor, mindist, maxdist )
+    returns the maxdist and mindist distance of any vertex from neighbor
+
+  returns:
+    the max absolute value
+
+  design:
+    for each vertex of facet that is not in neighbor
+      test the distance from vertex to neighbor
+*/
+realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist) {
+  vertexT *vertex, **vertexp;
+  realT dist, maxd, mind;
+  
+  FOREACHvertex_(facet->vertices)
+    vertex->seen= False;
+  FOREACHvertex_(neighbor->vertices)
+    vertex->seen= True;
+  mind= 0.0;
+  maxd= 0.0;
+  FOREACHvertex_(facet->vertices) {
+    if (!vertex->seen) {
+      zzinc_(Zbestdist);
+      qh_distplane(vertex->point, neighbor, &dist);
+      if (dist < mind)
+       mind= dist;
+      else if (dist > maxd)
+       maxd= dist;
+    }
+  }
+  *mindist= mind;
+  *maxdist= maxd;
+  mind= -mind;
+  if (maxd > mind)
+    return maxd;
+  else
+    return mind;
+} /* getdistance */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="normalize">-</a>
+
+  qh_normalize( normal, dim, toporient )
+    normalize a vector and report if too small
+    does not use min norm
+  
+  see:
+    qh_normalize2
+*/
+void qh_normalize (coordT *normal, int dim, boolT toporient) {
+  qh_normalize2( normal, dim, toporient, NULL, NULL);
+} /* normalize */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="normalize2">-</a>
+  
+  qh_normalize2( normal, dim, toporient, minnorm, ismin )
+    normalize a vector and report if too small
+    qh.MINdenom/MINdenom1 are the upper limits for divide overflow
+
+  returns:
+    normalized vector
+    flips sign if !toporient
+    if minnorm non-NULL, 
+      sets ismin if normal < minnorm
+
+  notes:
+    if zero norm
+       sets all elements to sqrt(1.0/dim)
+    if divide by zero (divzero ())
+       sets largest element to   +/-1
+       bumps Znearlysingular
+      
+  design:
+    computes norm
+    test for minnorm
+    if not near zero
+      normalizes normal
+    else if zero norm
+      sets normal to standard value
+    else
+      uses qh_divzero to normalize
+      if nearzero
+        sets norm to direction of maximum value
+*/
+void qh_normalize2 (coordT *normal, int dim, boolT toporient, 
+            realT *minnorm, boolT *ismin) {
+  int k;
+  realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3;
+  boolT zerodiv;
+
+  norm1= normal+1;
+  norm2= normal+2;
+  norm3= normal+3;
+  if (dim == 2)
+    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1));
+  else if (dim == 3)
+    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2));
+  else if (dim == 4) {
+    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2) 
+               + (*norm3)*(*norm3));
+  }else if (dim > 4) {
+    norm= (*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2) 
+               + (*norm3)*(*norm3);
+    for (k= dim-4, colp= normal+4; k--; colp++)
+      norm += (*colp) * (*colp);
+    norm= sqrt(norm);
+  }
+  if (minnorm) {
+    if (norm < *minnorm) 
+      *ismin= True;
+    else
+      *ismin= False;
+  }
+  wmin_(Wmindenom, norm);
+  if (norm > qh MINdenom) {
+    if (!toporient)
+      norm= -norm;
+    *normal /= norm;
+    *norm1 /= norm;
+    if (dim == 2)
+      ; /* all done */
+    else if (dim == 3)
+      *norm2 /= norm;
+    else if (dim == 4) {
+      *norm2 /= norm;
+      *norm3 /= norm;
+    }else if (dim >4) {
+      *norm2 /= norm;
+      *norm3 /= norm;
+      for (k= dim-4, colp= normal+4; k--; )
+        *colp++ /= norm;
+    }
+  }else if (norm == 0.0) {
+    temp= sqrt (1.0/dim);
+    for (k= dim, colp= normal; k--; )
+      *colp++ = temp;
+  }else {
+    if (!toporient)
+      norm= -norm;
+    for (k= dim, colp= normal; k--; colp++) { /* k used below */
+      temp= qh_divzero (*colp, norm, qh MINdenom_1, &zerodiv);
+      if (!zerodiv)
+       *colp= temp;
+      else {
+       maxp= qh_maxabsval(normal, dim);
+       temp= ((*maxp * norm >= 0.0) ? 1.0 : -1.0);
+       for (k= dim, colp= normal; k--; colp++)
+         *colp= 0.0;
+       *maxp= temp;
+       zzinc_(Znearlysingular);
+       trace0((qh ferr, "qh_normalize: norm=%2.2g too small during p%d\n", 
+              norm, qh furthest_id));
+       return;
+      }
+    }
+  }
+} /* normalize */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="projectpoint">-</a>
+  
+  qh_projectpoint( point, facet, dist )
+    project point onto a facet by dist
+
+  returns:
+    returns a new point
+    
+  notes:
+    if dist= distplane(point,facet)
+      this projects point to hyperplane
+    assumes qh_memfree_() is valid for normal_size
+*/
+pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist) {
+  pointT *newpoint, *np, *normal;
+  int normsize= qh normal_size,k;
+  void **freelistp; /* used !qh_NOmem */
+  
+  qh_memalloc_(normsize, freelistp, newpoint, pointT);
+  np= newpoint;
+  normal= facet->normal;
+  for(k= qh hull_dim; k--; )
+    *(np++)= *point++ - dist * *normal++;
+  return(newpoint);
+} /* projectpoint */
+
+  
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="setfacetplane">-</a>
+  
+  qh_setfacetplane( facet )
+    sets the hyperplane for a facet
+    if qh.RANDOMdist, joggles hyperplane
+
+  notes:
+    uses global buffers qh.gm_matrix and qh.gm_row
+    overwrites facet->normal if already defined
+    updates Wnewvertex if PRINTstatistics
+    sets facet->upperdelaunay if upper envelope of Delaunay triangulation
+
+  design:
+    copy vertex coordinates to qh.gm_matrix/gm_row
+    compute determinate
+    if nearzero
+      recompute determinate with gaussian elimination
+      if nearzero
+        force outside orientation by testing interior point
+*/
+void qh_setfacetplane(facetT *facet) {
+  pointT *point;
+  vertexT *vertex, **vertexp;
+  int k,i, normsize= qh normal_size, oldtrace= 0;
+  realT dist;
+  void **freelistp; /* used !qh_NOmem */
+  coordT *coord, *gmcoord;
+  pointT *point0= SETfirstt_(facet->vertices, vertexT)->point;
+  boolT nearzero= False;
+
+  zzinc_(Zsetplane);
+  if (!facet->normal)
+    qh_memalloc_(normsize, freelistp, facet->normal, coordT);
+  if (facet == qh tracefacet) {
+    oldtrace= qh IStracing;
+    qh IStracing= 5;
+    fprintf (qh ferr, "qh_setfacetplane: facet f%d created.\n", facet->id);
+    fprintf (qh ferr, "  Last point added to hull was p%d.", qh furthest_id);
+    if (zzval_(Ztotmerge))
+      fprintf(qh ferr, "  Last merge was #%d.", zzval_(Ztotmerge));
+    fprintf (qh ferr, "\n\nCurrent summary is:\n");
+      qh_printsummary (qh ferr);
+  }
+  if (qh hull_dim <= 4) {
+    i= 0;
+    if (qh RANDOMdist) {
+      gmcoord= qh gm_matrix;
+      FOREACHvertex_(facet->vertices) {
+        qh gm_row[i++]= gmcoord;
+       coord= vertex->point;
+       for (k= qh hull_dim; k--; )
+         *(gmcoord++)= *coord++ * qh_randomfactor();
+      }          
+    }else {
+      FOREACHvertex_(facet->vertices)
+       qh gm_row[i++]= vertex->point;
+    }
+    qh_sethyperplane_det(qh hull_dim, qh gm_row, point0, facet->toporient,
+                facet->normal, &facet->offset, &nearzero);
+  }
+  if (qh hull_dim > 4 || nearzero) {
+    i= 0;
+    gmcoord= qh gm_matrix;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->point != point0) {
+       qh gm_row[i++]= gmcoord;
+       coord= vertex->point;
+       point= point0;
+       for(k= qh hull_dim; k--; )
+         *(gmcoord++)= *coord++ - *point++;
+      }
+    }
+    qh gm_row[i]= gmcoord;  /* for areasimplex */
+    if (qh RANDOMdist) {
+      gmcoord= qh gm_matrix;
+      for (i= qh hull_dim-1; i--; ) {
+       for (k= qh hull_dim; k--; )
+         *(gmcoord++) *= qh_randomfactor();
+      }
+    }
+    qh_sethyperplane_gauss(qh hull_dim, qh gm_row, point0, facet->toporient,
+               facet->normal, &facet->offset, &nearzero);
+    if (nearzero) { 
+      if (qh_orientoutside (facet)) {
+       trace0((qh ferr, "qh_setfacetplane: flipped orientation after testing interior_point during p%d\n", qh furthest_id));
+      /* this is part of using Gaussian Elimination.  For example in 5-d
+          1 1 1 1 0
+          1 1 1 1 1
+          0 0 0 1 0
+          0 1 0 0 0
+          1 0 0 0 0
+          norm= 0.38 0.38 -0.76 0.38 0
+        has a determinate of 1, but g.e. after subtracting pt. 0 has
+        0's in the diagonal, even with full pivoting.  It does work
+        if you subtract pt. 4 instead. */
+      }
+    }
+  }
+  facet->upperdelaunay= False;
+  if (qh DELAUNAY) {
+    if (qh UPPERdelaunay) {     /* matches qh_triangulate_facet and qh.lower_threshold in qh_initbuild */
+      if (facet->normal[qh hull_dim -1] >= qh ANGLEround * qh_ZEROdelaunay)
+        facet->upperdelaunay= True;
+    }else {
+      if (facet->normal[qh hull_dim -1] > -qh ANGLEround * qh_ZEROdelaunay)
+        facet->upperdelaunay= True;
+    }
+  }
+  if (qh PRINTstatistics || qh IStracing || qh TRACElevel || qh JOGGLEmax < REALmax) {
+    qh old_randomdist= qh RANDOMdist;
+    qh RANDOMdist= False;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->point != point0) {
+       boolT istrace= False;
+       zinc_(Zdiststat);
+        qh_distplane(vertex->point, facet, &dist);
+        dist= fabs_(dist);
+        zinc_(Znewvertex);
+        wadd_(Wnewvertex, dist);
+        if (dist > wwval_(Wnewvertexmax)) {
+          wwval_(Wnewvertexmax)= dist;
+         if (dist > qh max_outside) {
+           qh max_outside= dist;  /* used by qh_maxouter() */
+           if (dist > qh TRACEdist) 
+             istrace= True;
+         }
+       }else if (-dist > qh TRACEdist)
+         istrace= True;
+       if (istrace) {
+         fprintf (qh ferr, "qh_setfacetplane: ====== vertex p%d (v%d) increases max_outside to %2.2g for new facet f%d last p%d\n",
+               qh_pointid(vertex->point), vertex->id, dist, facet->id, qh furthest_id);
+         qh_errprint ("DISTANT", facet, NULL, NULL, NULL);
+       }
+      }
+    }
+    qh RANDOMdist= qh old_randomdist;
+  }
+  if (qh IStracing >= 3) {
+    fprintf (qh ferr, "qh_setfacetplane: f%d offset %2.2g normal: ",
+            facet->id, facet->offset);
+    for (k=0; k < qh hull_dim; k++)
+      fprintf (qh ferr, "%2.2g ", facet->normal[k]);
+    fprintf (qh ferr, "\n");
+  }
+  if (facet == qh tracefacet)
+    qh IStracing= oldtrace;
+} /* setfacetplane */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sethyperplane_det">-</a>
+  
+  qh_sethyperplane_det( dim, rows, point0, toporient, normal, offset, nearzero )
+    given dim X dim array indexed by rows[], one row per point, 
+        toporient (flips all signs),
+        and point0 (any row)
+    set normalized hyperplane equation from oriented simplex
+
+  returns:
+    normal (normalized)
+    offset (places point0 on the hyperplane)
+    sets nearzero if hyperplane not through points
+
+  notes:
+    only defined for dim == 2..4
+    rows[] is not modified
+    solves det(P-V_0, V_n-V_0, ..., V_1-V_0)=0, i.e. every point is on hyperplane
+    see Bower & Woodworth, A programmer's geometry, Butterworths 1983.
+
+  derivation of 3-d minnorm
+    Goal: all vertices V_i within qh.one_merge of hyperplane
+    Plan: exactly translate the facet so that V_0 is the origin
+          exactly rotate the facet so that V_1 is on the x-axis and y_2=0.
+          exactly rotate the effective perturbation to only effect n_0
+            this introduces a factor of sqrt(3)
+    n_0 = ((y_2-y_0)*(z_1-z_0) - (z_2-z_0)*(y_1-y_0)) / norm
+    Let M_d be the max coordinate difference
+    Let M_a be the greater of M_d and the max abs. coordinate
+    Let u be machine roundoff and distround be max error for distance computation
+    The max error for n_0 is sqrt(3) u M_a M_d / norm.  n_1 is approx. 1 and n_2 is approx. 0
+    The max error for distance of V_1 is sqrt(3) u M_a M_d M_d / norm.  Offset=0 at origin
+    Then minnorm = 1.8 u M_a M_d M_d / qh.ONEmerge
+    Note that qh.one_merge is approx. 45.5 u M_a and norm is usually about M_d M_d
+
+  derivation of 4-d minnorm
+    same as above except rotate the facet so that V_1 on x-axis and w_2, y_3, w_3=0
+     [if two vertices fixed on x-axis, can rotate the other two in yzw.]
+    n_0 = det3_(...) = y_2 det2_(z_1, w_1, z_3, w_3) = - y_2 w_1 z_3
+     [all other terms contain at least two factors nearly zero.]
+    The max error for n_0 is sqrt(4) u M_a M_d M_d / norm
+    Then minnorm = 2 u M_a M_d M_d M_d / qh.ONEmerge
+    Note that qh.one_merge is approx. 82 u M_a and norm is usually about M_d M_d M_d
+*/
+void qh_sethyperplane_det (int dim, coordT **rows, coordT *point0, 
+          boolT toporient, coordT *normal, realT *offset, boolT *nearzero) {
+  realT maxround, dist;
+  int i;
+  pointT *point;
+
+
+  if (dim == 2) {
+    normal[0]= dY(1,0);
+    normal[1]= dX(0,1);
+    qh_normalize2 (normal, dim, toporient, NULL, NULL);
+    *offset= -(point0[0]*normal[0]+point0[1]*normal[1]);
+    *nearzero= False;  /* since nearzero norm => incident points */
+  }else if (dim == 3) {
+    normal[0]= det2_(dY(2,0), dZ(2,0),
+                    dY(1,0), dZ(1,0));
+    normal[1]= det2_(dX(1,0), dZ(1,0),
+                    dX(2,0), dZ(2,0));
+    normal[2]= det2_(dX(2,0), dY(2,0),
+                    dX(1,0), dY(1,0));
+    qh_normalize2 (normal, dim, toporient, NULL, NULL);
+    *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
+              + point0[2]*normal[2]);
+    maxround= qh DISTround;
+    for (i=dim; i--; ) {
+      point= rows[i];
+      if (point != point0) {
+        dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
+              + point[2]*normal[2]);
+        if (dist > maxround || dist < -maxround) {
+         *nearzero= True;
+         break;
+       }
+      }
+    }
+  }else if (dim == 4) {
+    normal[0]= - det3_(dY(2,0), dZ(2,0), dW(2,0),
+                       dY(1,0), dZ(1,0), dW(1,0),
+                       dY(3,0), dZ(3,0), dW(3,0));
+    normal[1]=   det3_(dX(2,0), dZ(2,0), dW(2,0),
+                       dX(1,0), dZ(1,0), dW(1,0),
+                       dX(3,0), dZ(3,0), dW(3,0));
+    normal[2]= - det3_(dX(2,0), dY(2,0), dW(2,0),
+                       dX(1,0), dY(1,0), dW(1,0),
+                       dX(3,0), dY(3,0), dW(3,0));
+    normal[3]=   det3_(dX(2,0), dY(2,0), dZ(2,0),
+                       dX(1,0), dY(1,0), dZ(1,0),
+                       dX(3,0), dY(3,0), dZ(3,0));
+    qh_normalize2 (normal, dim, toporient, NULL, NULL);
+    *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
+              + point0[2]*normal[2] + point0[3]*normal[3]);
+    maxround= qh DISTround;
+    for (i=dim; i--; ) {
+      point= rows[i];
+      if (point != point0) {
+        dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
+              + point[2]*normal[2] + point[3]*normal[3]);
+        if (dist > maxround || dist < -maxround) {
+         *nearzero= True;
+         break;
+       }
+      }
+    }
+  }
+  if (*nearzero) {
+    zzinc_(Zminnorm);
+    trace0((qh ferr, "qh_sethyperplane_det: degenerate norm during p%d.\n", qh furthest_id));
+    zzinc_(Znearlysingular);
+  }
+} /* sethyperplane_det */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sethyperplane_gauss">-</a>
+  
+  qh_sethyperplane_gauss( dim, rows, point0, toporient, normal, offset, nearzero )
+    given (dim-1) X dim array of rows[i]= V_{i+1} - V_0 (point0)
+    set normalized hyperplane equation from oriented simplex
+
+  returns:
+    normal (normalized)
+    offset (places point0 on the hyperplane)
+
+  notes:
+    if nearzero
+      orientation may be incorrect because of incorrect sign flips in gausselim
+    solves [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0 .. 0 1] 
+        or [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0] 
+    i.e., N is normal to the hyperplane, and the unnormalized
+        distance to [0 .. 1] is either 1 or   0
+
+  design:
+    perform gaussian elimination
+    flip sign for negative values
+    perform back substitution 
+    normalize result
+    compute offset
+*/
+void qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0, 
+               boolT toporient, coordT *normal, coordT *offset, boolT *nearzero) {
+  coordT *pointcoord, *normalcoef;
+  int k;
+  boolT sign= toporient, nearzero2= False;
+  
+  qh_gausselim(rows, dim-1, dim, &sign, nearzero);
+  for(k= dim-1; k--; ) {
+    if ((rows[k])[k] < 0)
+      sign ^= 1;
+  }
+  if (*nearzero) {
+    zzinc_(Znearlysingular);
+    trace0((qh ferr, "qh_sethyperplane_gauss: nearly singular or axis parallel hyperplane during p%d.\n", qh furthest_id));
+    qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
+  }else {
+    qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
+    if (nearzero2) {
+      zzinc_(Znearlysingular);
+      trace0((qh ferr, "qh_sethyperplane_gauss: singular or axis parallel hyperplane at normalization during p%d.\n", qh furthest_id));
+    }
+  }
+  if (nearzero2)
+    *nearzero= True;
+  qh_normalize2(normal, dim, True, NULL, NULL);
+  pointcoord= point0;
+  normalcoef= normal;
+  *offset= -(*pointcoord++ * *normalcoef++);
+  for(k= dim-1; k--; )
+    *offset -= *pointcoord++ * *normalcoef++;
+} /* sethyperplane_gauss */
+
+  
+
diff --git a/extern/qhull/src/geom.h b/extern/qhull/src/geom.h
new file mode 100755 (executable)
index 0000000..32440cf
--- /dev/null
@@ -0,0 +1,177 @@
+/*<html><pre>  -<a                             href="qh-geom.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+  geom.h 
+    header file for geometric routines
+
+   see qh-geom.htm and geom.c
+
+   copyright (c) 1993-2002 The Geometry Center        
+*/
+
+#ifndef qhDEFgeom
+#define qhDEFgeom 1
+
+/* ============ -macros- ======================== */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="fabs_">-</a>
+   
+  fabs_(a)
+    returns the absolute value of a
+*/
+#define fabs_( a ) ((( a ) < 0 ) ? -( a ):( a ))
+               
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="fmax_">-</a>
+  
+  fmax_(a,b)
+    returns the maximum value of a and b
+*/
+#define fmax_( a,b )  ( ( a ) < ( b ) ? ( b ) : ( a ) )
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="fmin_">-</a>
+
+  fmin_(a,b)
+    returns the minimum value of a and b
+*/
+#define fmin_( a,b )  ( ( a ) > ( b ) ? ( b ) : ( a ) )
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="maximize_">-</a>
+
+  maximize_(maxval, val)
+    set maxval to val if val is greater than maxval
+*/
+#define maximize_( maxval, val ) {if (( maxval ) < ( val )) ( maxval )= ( val );}
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="minimize_">-</a>
+
+  minimize_(minval, val)
+    set minval to val if val is less than minval
+*/
+#define minimize_( minval, val ) {if (( minval ) > ( val )) ( minval )= ( val );}
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="det2_">-</a>
+
+  det2_(a1, a2,     
+        b1, b2)
+  
+    compute a 2-d determinate
+*/
+#define det2_( a1,a2,b1,b2 ) (( a1 )*( b2 ) - ( a2 )*( b1 ))
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="det3_">-</a>
+  
+  det3_(a1, a2, a3,    
+       b1, b2, b3,
+       c1, c2, c3)
+  
+    compute a 3-d determinate
+*/
+#define det3_( a1,a2,a3,b1,b2,b3,c1,c2,c3 ) ( ( a1 )*det2_( b2,b3,c2,c3 ) \
+                - ( b1 )*det2_( a2,a3,c2,c3 ) + ( c1 )*det2_( a2,a3,b2,b3 ) )
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="dX">-</a>
+  
+  dX( p1, p2 )
+  dY( p1, p2 )
+  dZ( p1, p2 )
+  
+    given two indices into rows[],
+
+    compute the difference between X, Y, or Z coordinates
+*/
+#define dX( p1,p2 )  ( *( rows[p1] ) - *( rows[p2] ))
+#define dY( p1,p2 )  ( *( rows[p1]+1 ) - *( rows[p2]+1 ))
+#define dZ( p1,p2 )  ( *( rows[p1]+2 ) - *( rows[p2]+2 ))
+#define dW( p1,p2 )  ( *( rows[p1]+3 ) - *( rows[p2]+3 ))
+
+/*============= prototypes in alphabetical order, infrequent at end ======= */
+
+void    qh_backnormal (realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero);
+void   qh_distplane (pointT *point, facetT *facet, realT *dist);
+facetT *qh_findbest (pointT *point, facetT *startfacet,
+                    boolT bestoutside, boolT isnewfacets, boolT noupper,
+                    realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbesthorizon (boolT ischeckmax, pointT *point, 
+                    facetT *startfacet, boolT noupper, realT *bestdist, int *numpart);
+facetT *qh_findbestnew (pointT *point, facetT *startfacet, realT *dist, 
+                    boolT bestoutside, boolT *isoutside, int *numpart);
+void   qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero);
+realT   qh_getangle(pointT *vect1, pointT *vect2);
+pointT *qh_getcenter(setT *vertices);
+pointT *qh_getcentrum(facetT *facet);
+realT   qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist);
+void    qh_normalize (coordT *normal, int dim, boolT toporient);
+void    qh_normalize2 (coordT *normal, int dim, boolT toporient, 
+            realT *minnorm, boolT *ismin);
+pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist);
+
+void    qh_setfacetplane(facetT *newfacets);
+void   qh_sethyperplane_det (int dim, coordT **rows, coordT *point0, 
+              boolT toporient, coordT *normal, realT *offset, boolT *nearzero);
+void   qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0, 
+            boolT toporient, coordT *normal, coordT *offset, boolT *nearzero);
+boolT   qh_sharpnewfacets (void);
+
+/*========= infrequently used code in geom2.c =============*/
+
+
+coordT *qh_copypoints (coordT *points, int numpoints, int dimension);
+void    qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]);
+realT  qh_determinant (realT **rows, int dim, boolT *nearzero);
+realT   qh_detjoggle (pointT *points, int numpoints, int dimension);
+void    qh_detroundoff (void);
+realT   qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero);
+realT   qh_distnorm (int dim, pointT *point, pointT *normal, realT *offsetp);
+realT   qh_distround (int dimension, realT maxabs, realT maxsumabs);
+realT   qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv);
+realT   qh_facetarea (facetT *facet);
+realT   qh_facetarea_simplex (int dim, coordT *apex, setT *vertices, 
+          vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset);
+pointT *qh_facetcenter (setT *vertices);
+facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp, facetT **facetlist);
+void    qh_getarea (facetT *facetlist);
+boolT   qh_gram_schmidt(int dim, realT **rows);
+boolT   qh_inthresholds (coordT *normal, realT *angle);
+void    qh_joggleinput (void);
+realT  *qh_maxabsval (realT *normal, int dim);
+setT   *qh_maxmin(pointT *points, int numpoints, int dimension);
+realT   qh_maxouter (void);
+void    qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex);
+realT   qh_minabsval (realT *normal, int dim);
+int     qh_mindiff (realT *vecA, realT *vecB, int dim);
+boolT   qh_orientoutside (facetT *facet);
+void    qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
+coordT  qh_pointdist(pointT *point1, pointT *point2, int dim);
+void    qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol);
+void    qh_printpoints (FILE *fp, char *string, setT *points);
+void    qh_projectinput (void);
+void   qh_projectpoints (signed char *project, int n, realT *points, 
+             int numpoints, int dim, realT *newpoints, int newdim);
+int     qh_rand( void);
+void    qh_srand( int seed);
+realT   qh_randomfactor (void);
+void    qh_randommatrix (realT *buffer, int dim, realT **row);
+void    qh_rotateinput (realT **rows);
+void    qh_rotatepoints (realT *points, int numpoints, int dim, realT **rows);
+void    qh_scaleinput (void);
+void    qh_scalelast (coordT *points, int numpoints, int dim, coordT low,
+                  coordT high, coordT newhigh);
+void   qh_scalepoints (pointT *points, int numpoints, int dim,
+               realT *newlows, realT *newhighs);
+boolT   qh_sethalfspace (int dim, coordT *coords, coordT **nextp, 
+              coordT *normal, coordT *offset, coordT *feasible);
+coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
+pointT *qh_voronoi_center (int dim, setT *points);
+
+#endif /* qhDEFgeom */
+
+
+
diff --git a/extern/qhull/src/geom2.c b/extern/qhull/src/geom2.c
new file mode 100755 (executable)
index 0000000..bd58ce1
--- /dev/null
@@ -0,0 +1,2160 @@
+/*<html><pre>  -<a                             href="qh-geom.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+
+   geom2.c 
+   infrequently used geometric routines of qhull
+
+   see qh-geom.htm and geom.h
+
+   copyright (c) 1993-2002 The Geometry Center        
+
+   frequently used code goes into geom.c
+*/
+   
+#include "qhull_a.h"
+   
+/*================== functions in alphabetic order ============*/
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="copypoints">-</a>
+
+  qh_copypoints( points, numpoints, dimension)
+    return malloc'd copy of points
+*/
+coordT *qh_copypoints (coordT *points, int numpoints, int dimension) {
+  int size;
+  coordT *newpoints;
+
+  size= numpoints * dimension * sizeof(coordT);
+  if (!(newpoints=(coordT*)malloc(size))) {
+    fprintf(qh ferr, "qhull error: insufficient memory to copy %d points\n",
+        numpoints);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  memcpy ((char *)newpoints, (char *)points, size);
+  return newpoints;
+} /* copypoints */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="crossproduct">-</a>
+  
+  qh_crossproduct( dim, vecA, vecB, vecC )
+    crossproduct of 2 dim vectors
+    C= A x B
+  
+  notes:
+    from Glasner, Graphics Gems I, p. 639
+    only defined for dim==3
+*/
+void qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
+
+  if (dim == 3) {
+    vecC[0]=   det2_(vecA[1], vecA[2],
+                    vecB[1], vecB[2]);
+    vecC[1]= - det2_(vecA[0], vecA[2],
+                    vecB[0], vecB[2]);
+    vecC[2]=   det2_(vecA[0], vecA[1],
+                    vecB[0], vecB[1]);
+  }
+} /* vcross */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="determinant">-</a>
+  
+  qh_determinant( rows, dim, nearzero )
+    compute signed determinant of a square matrix
+    uses qh.NEARzero to test for degenerate matrices
+
+  returns:
+    determinant
+    overwrites rows and the matrix
+    if dim == 2 or 3
+      nearzero iff determinant < qh NEARzero[dim-1]
+      (not quite correct, not critical)
+    if dim >= 4
+      nearzero iff diagonal[k] < qh NEARzero[k]
+*/
+realT qh_determinant (realT **rows, int dim, boolT *nearzero) {
+  realT det=0;
+  int i;
+  boolT sign= False;
+
+  *nearzero= False;
+  if (dim < 2) {
+    fprintf (qh ferr, "qhull internal error (qh_determinate): only implemented for dimension >= 2\n");
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }else if (dim == 2) {
+    det= det2_(rows[0][0], rows[0][1],
+                rows[1][0], rows[1][1]);
+    if (fabs_(det) < qh NEARzero[1])  /* not really correct, what should this be? */
+      *nearzero= True;
+  }else if (dim == 3) {
+    det= det3_(rows[0][0], rows[0][1], rows[0][2],
+                rows[1][0], rows[1][1], rows[1][2],
+                rows[2][0], rows[2][1], rows[2][2]);
+    if (fabs_(det) < qh NEARzero[2])  /* not really correct, what should this be? */
+      *nearzero= True;
+  }else {      
+    qh_gausselim(rows, dim, dim, &sign, nearzero);  /* if nearzero, diagonal still ok*/
+    det= 1.0;
+    for (i= dim; i--; )
+      det *= (rows[i])[i];
+    if (sign)
+      det= -det;
+  }
+  return det;
+} /* determinant */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="detjoggle">-</a>
+  
+  qh_detjoggle( points, numpoints, dimension )
+    determine default max joggle for point array
+      as qh_distround * qh_JOGGLEdefault
+
+  returns:
+    initial value for JOGGLEmax from points and REALepsilon
+
+  notes:
+    computes DISTround since qh_maxmin not called yet
+    if qh SCALElast, last dimension will be scaled later to MAXwidth
+
+    loop duplicated from qh_maxmin
+*/
+realT qh_detjoggle (pointT *points, int numpoints, int dimension) {
+  realT abscoord, distround, joggle, maxcoord, mincoord;
+  pointT *point, *pointtemp;
+  realT maxabs= -REALmax;
+  realT sumabs= 0;
+  realT maxwidth= 0;
+  int k;
+
+  for (k= 0; k < dimension; k++) {
+    if (qh SCALElast && k == dimension-1)
+      abscoord= maxwidth;
+    else if (qh DELAUNAY && k == dimension-1) /* will qh_setdelaunay() */
+      abscoord= 2 * maxabs * maxabs;  /* may be low by qh hull_dim/2 */
+    else {
+      maxcoord= -REALmax;
+      mincoord= REALmax;
+      FORALLpoint_(points, numpoints) {
+       maximize_(maxcoord, point[k]);
+        minimize_(mincoord, point[k]);
+      }
+      maximize_(maxwidth, maxcoord-mincoord);
+      abscoord= fmax_(maxcoord, -mincoord);
+    }
+    sumabs += abscoord;
+    maximize_(maxabs, abscoord);
+  } /* for k */
+  distround= qh_distround (qh hull_dim, maxabs, sumabs);
+  joggle= distround * qh_JOGGLEdefault;
+  maximize_(joggle, REALepsilon * qh_JOGGLEdefault);
+  trace2((qh ferr, "qh_detjoggle: joggle=%2.2g maxwidth=%2.2g\n", joggle, maxwidth));
+  return joggle;
+} /* detjoggle */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="detroundoff">-</a>
+  
+  qh_detroundoff()
+    determine maximum roundoff errors from
+      REALepsilon, REALmax, REALmin, qh.hull_dim, qh.MAXabs_coord, 
+      qh.MAXsumcoord, qh.MAXwidth, qh.MINdenom_1
+
+    accounts for qh.SETroundoff, qh.RANDOMdist, qh MERGEexact
+      qh.premerge_cos, qh.postmerge_cos, qh.premerge_centrum,
+      qh.postmerge_centrum, qh.MINoutside,
+      qh_RATIOnearinside, qh_COPLANARratio, qh_WIDEcoplanar
+
+  returns:
+    sets qh.DISTround, etc. (see below)
+    appends precision constants to qh.qhull_options
+
+  see:
+    qh_maxmin() for qh.NEARzero
+
+  design:
+    determine qh.DISTround for distance computations
+    determine minimum denominators for qh_divzero
+    determine qh.ANGLEround for angle computations
+    adjust qh.premerge_cos,... for roundoff error
+    determine qh.ONEmerge for maximum error due to a single merge
+    determine qh.NEARinside, qh.MAXcoplanar, qh.MINvisible,
+      qh.MINoutside, qh.WIDEfacet
+    initialize qh.max_vertex and qh.minvertex
+*/
+void qh_detroundoff (void) {
+
+  qh_option ("_max-width", NULL, &qh MAXwidth);
+  if (!qh SETroundoff) {
+    qh DISTround= qh_distround (qh hull_dim, qh MAXabs_coord, qh MAXsumcoord);
+    if (qh RANDOMdist)
+      qh DISTround += qh RANDOMfactor * qh MAXabs_coord;
+    qh_option ("Error-roundoff", NULL, &qh DISTround);
+  }
+  qh MINdenom= qh MINdenom_1 * qh MAXabs_coord;
+  qh MINdenom_1_2= sqrt (qh MINdenom_1 * qh hull_dim) ;  /* if will be normalized */
+  qh MINdenom_2= qh MINdenom_1_2 * qh MAXabs_coord;
+                                              /* for inner product */
+  qh ANGLEround= 1.01 * qh hull_dim * REALepsilon;
+  if (qh RANDOMdist)
+    qh ANGLEround += qh RANDOMfactor;
+  if (qh premerge_cos < REALmax/2) {
+    qh premerge_cos -= qh ANGLEround;
+    if (qh RANDOMdist) 
+      qh_option ("Angle-premerge-with-random", NULL, &qh premerge_cos);
+  }
+  if (qh postmerge_cos < REALmax/2) {
+    qh postmerge_cos -= qh ANGLEround;
+    if (qh RANDOMdist)
+      qh_option ("Angle-postmerge-with-random", NULL, &qh postmerge_cos);
+  }
+  qh premerge_centrum += 2 * qh DISTround;    /*2 for centrum and distplane()*/
+  qh postmerge_centrum += 2 * qh DISTround;
+  if (qh RANDOMdist && (qh MERGEexact || qh PREmerge))
+    qh_option ("Centrum-premerge-with-random", NULL, &qh premerge_centrum);
+  if (qh RANDOMdist && qh POSTmerge)
+    qh_option ("Centrum-postmerge-with-random", NULL, &qh postmerge_centrum);
+  { /* compute ONEmerge, max vertex offset for merging simplicial facets */
+    realT maxangle= 1.0, maxrho;
+    
+    minimize_(maxangle, qh premerge_cos);
+    minimize_(maxangle, qh postmerge_cos);
+    /* max diameter * sin theta + DISTround for vertex to its hyperplane */
+    qh ONEmerge= sqrt (qh hull_dim) * qh MAXwidth *
+      sqrt (1.0 - maxangle * maxangle) + qh DISTround;  
+    maxrho= qh hull_dim * qh premerge_centrum + qh DISTround;
+    maximize_(qh ONEmerge, maxrho);
+    maxrho= qh hull_dim * qh postmerge_centrum + qh DISTround;
+    maximize_(qh ONEmerge, maxrho);
+    if (qh MERGING)
+      qh_option ("_one-merge", NULL, &qh ONEmerge);
+  }
+  qh NEARinside= qh ONEmerge * qh_RATIOnearinside; /* only used if qh KEEPnearinside */
+  if (qh JOGGLEmax < REALmax/2 && (qh KEEPcoplanar || qh KEEPinside)) {
+    realT maxdist;            /* adjust qh.NEARinside for joggle */
+    qh KEEPnearinside= True;   
+    maxdist= sqrt (qh hull_dim) * qh JOGGLEmax + qh DISTround;
+    maxdist= 2*maxdist;        /* vertex and coplanar point can joggle in opposite directions */
+    maximize_(qh NEARinside, maxdist);  /* must agree with qh_nearcoplanar() */
+  }
+  if (qh KEEPnearinside)
+    qh_option ("_near-inside", NULL, &qh NEARinside);
+  if (qh JOGGLEmax < qh DISTround) {
+    fprintf (qh ferr, "qhull error: the joggle for 'QJn', %.2g, is below roundoff for distance computations, %.2g\n",
+         qh JOGGLEmax, qh DISTround);
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  if (qh MINvisible > REALmax/2) {
+    if (!qh MERGING)
+      qh MINvisible= qh DISTround;
+    else if (qh hull_dim <= 3)
+      qh MINvisible= qh premerge_centrum;
+    else
+      qh MINvisible= qh_COPLANARratio * qh premerge_centrum;
+    if (qh APPROXhull && qh MINvisible > qh MINoutside)
+      qh MINvisible= qh MINoutside;
+    qh_option ("Visible-distance", NULL, &qh MINvisible);
+  }
+  if (qh MAXcoplanar > REALmax/2) {
+    qh MAXcoplanar= qh MINvisible;
+    qh_option ("U-coplanar-distance", NULL, &qh MAXcoplanar);
+  }
+  if (!qh APPROXhull) {             /* user may specify qh MINoutside */
+    qh MINoutside= 2 * qh MINvisible;
+    if (qh premerge_cos < REALmax/2) 
+      maximize_(qh MINoutside, (1- qh premerge_cos) * qh MAXabs_coord);
+    qh_option ("Width-outside", NULL, &qh MINoutside);
+  }
+  qh WIDEfacet= qh MINoutside;
+  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MAXcoplanar); 
+  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MINvisible); 
+  qh_option ("_wide-facet", NULL, &qh WIDEfacet);
+  if (qh MINvisible > qh MINoutside + 3 * REALepsilon 
+  && !qh BESToutside && !qh FORCEoutput)
+    fprintf (qh ferr, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g.  Flipped facets are likely.\n",
+            qh MINvisible, qh MINoutside);
+  qh max_vertex= qh DISTround;
+  qh min_vertex= -qh DISTround;
+  /* numeric constants reported in printsummary */
+} /* detroundoff */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="detsimplex">-</a>
+  
+  qh_detsimplex( apex, points, dim, nearzero )
+    compute determinant of a simplex with point apex and base points
+
+  returns:
+     signed determinant and nearzero from qh_determinant
+
+  notes:
+     uses qh.gm_matrix/qh.gm_row (assumes they're big enough)
+
+  design:
+    construct qm_matrix by subtracting apex from points
+    compute determinate
+*/
+realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero) {
+  pointT *coorda, *coordp, *gmcoord, *point, **pointp;
+  coordT **rows;
+  int k,  i=0;
+  realT det;
+
+  zinc_(Zdetsimplex);
+  gmcoord= qh gm_matrix;
+  rows= qh gm_row;
+  FOREACHpoint_(points) {
+    if (i == dim)
+      break;
+    rows[i++]= gmcoord;
+    coordp= point;
+    coorda= apex;
+    for (k= dim; k--; )
+      *(gmcoord++)= *coordp++ - *coorda++;
+  }
+  if (i < dim) {
+    fprintf (qh ferr, "qhull internal error (qh_detsimplex): #points %d < dimension %d\n", 
+               i, dim);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  det= qh_determinant (rows, dim, nearzero);
+  trace2((qh ferr, "qh_detsimplex: det=%2.2g for point p%d, dim %d, nearzero? %d\n",
+         det, qh_pointid(apex), dim, *nearzero)); 
+  return det;
+} /* detsimplex */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="distnorm">-</a>
+  
+  qh_distnorm( dim, point, normal, offset )
+    return distance from point to hyperplane at normal/offset
+
+  returns:
+    dist
+  
+  notes:  
+    dist > 0 if point is outside of hyperplane
+  
+  see:
+    qh_distplane in geom.c
+*/
+realT qh_distnorm (int dim, pointT *point, pointT *normal, realT *offsetp) {
+  coordT *normalp= normal, *coordp= point;
+  realT dist;
+  int k;
+
+  dist= *offsetp;
+  for (k= dim; k--; )
+    dist += *(coordp++) * *(normalp++);
+  return dist;
+} /* distnorm */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="distround">-</a>
+
+  qh_distround ( dimension, maxabs, maxsumabs )
+    compute maximum round-off error for a distance computation
+      to a normalized hyperplane
+    maxabs is the maximum absolute value of a coordinate
+    maxsumabs is the maximum possible sum of absolute coordinate values
+
+  returns:
+    max dist round for REALepsilon
+
+  notes:
+    calculate roundoff error according to
+    Lemma 3.2-1 of Golub and van Loan "Matrix Computation"
+    use sqrt(dim) since one vector is normalized
+      or use maxsumabs since one vector is < 1
+*/
+realT qh_distround (int dimension, realT maxabs, realT maxsumabs) {
+  realT maxdistsum, maxround;
+
+  maxdistsum= sqrt (dimension) * maxabs;
+  minimize_( maxdistsum, maxsumabs);
+  maxround= REALepsilon * (dimension * maxdistsum * 1.01 + maxabs);
+              /* adds maxabs for offset */
+  trace4((qh ferr, "qh_distround: %2.2g maxabs %2.2g maxsumabs %2.2g maxdistsum %2.2g\n",
+                maxround, maxabs, maxsumabs, maxdistsum));
+  return maxround;
+} /* distround */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="divzero">-</a>
+  
+  qh_divzero( numer, denom, mindenom1, zerodiv )
+    divide by a number that's nearly zero
+    mindenom1= minimum denominator for dividing into 1.0
+
+  returns:
+    quotient
+    sets zerodiv and returns 0.0 if it would overflow
+  
+  design:
+    if numer is nearly zero and abs(numer) < abs(denom)
+      return numer/denom
+    else if numer is nearly zero
+      return 0 and zerodiv
+    else if denom/numer non-zero
+      return numer/denom
+    else
+      return 0 and zerodiv
+*/
+realT qh_divzero (realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
+  realT temp, numerx, denomx;
+  
+
+  if (numer < mindenom1 && numer > -mindenom1) {
+    numerx= fabs_(numer);
+    denomx= fabs_(denom);
+    if (numerx < denomx) {
+      *zerodiv= False;
+      return numer/denom;
+    }else {
+      *zerodiv= True;
+      return 0.0;
+    }
+  }
+  temp= denom/numer;
+  if (temp > mindenom1 || temp < -mindenom1) {
+    *zerodiv= False;
+    return numer/denom;
+  }else {
+    *zerodiv= True;
+    return 0.0;
+  }
+} /* divzero */
+  
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="facetarea">-</a>
+
+  qh_facetarea( facet )
+    return area for a facet
+  
+  notes:
+    if non-simplicial, 
+      uses centrum to triangulate facet and sums the projected areas.
+    if (qh DELAUNAY),
+      computes projected area instead for last coordinate
+    assumes facet->normal exists
+    projecting tricoplanar facets to the hyperplane does not appear to make a difference
+  
+  design:
+    if simplicial
+      compute area
+    else
+      for each ridge
+        compute area from centrum to ridge
+    negate area if upper Delaunay facet
+*/
+realT qh_facetarea (facetT *facet) {
+  vertexT *apex;
+  pointT *centrum;
+  realT area= 0.0;
+  ridgeT *ridge, **ridgep;
+
+  if (facet->simplicial) {
+    apex= SETfirstt_(facet->vertices, vertexT);
+    area= qh_facetarea_simplex (qh hull_dim, apex->point, facet->vertices, 
+                    apex, facet->toporient, facet->normal, &facet->offset);
+  }else {
+    if (qh CENTERtype == qh_AScentrum)
+      centrum= facet->center;
+    else
+      centrum= qh_getcentrum (facet);
+    FOREACHridge_(facet->ridges) 
+      area += qh_facetarea_simplex (qh hull_dim, centrum, ridge->vertices, 
+                 NULL, (ridge->top == facet),  facet->normal, &facet->offset);
+    if (qh CENTERtype != qh_AScentrum)
+      qh_memfree (centrum, qh normal_size);
+  }
+  if (facet->upperdelaunay && qh DELAUNAY)
+    area= -area;  /* the normal should be [0,...,1] */
+  trace4((qh ferr, "qh_facetarea: f%d area %2.2g\n", facet->id, area)); 
+  return area;
+} /* facetarea */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="facetarea_simplex">-</a>
+
+  qh_facetarea_simplex( dim, apex, vertices, notvertex, toporient, normal, offset )
+    return area for a simplex defined by 
+      an apex, a base of vertices, an orientation, and a unit normal
+    if simplicial or tricoplanar facet, 
+      notvertex is defined and it is skipped in vertices
+  
+  returns:
+    computes area of simplex projected to plane [normal,offset]
+    returns 0 if vertex too far below plane (qh WIDEfacet)
+      vertex can't be apex of tricoplanar facet
+  
+  notes:
+    if (qh DELAUNAY),
+      computes projected area instead for last coordinate
+    uses qh gm_matrix/gm_row and qh hull_dim
+    helper function for qh_facetarea
+  
+  design:
+    if Notvertex
+      translate simplex to apex
+    else
+      project simplex to normal/offset
+      translate simplex to apex
+    if Delaunay
+      set last row/column to 0 with -1 on diagonal 
+    else
+      set last row to Normal
+    compute determinate
+    scale and flip sign for area
+*/
+realT qh_facetarea_simplex (int dim, coordT *apex, setT *vertices, 
+        vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset) {
+  pointT *coorda, *coordp, *gmcoord;
+  coordT **rows, *normalp;
+  int k,  i=0;
+  realT area, dist;
+  vertexT *vertex, **vertexp;
+  boolT nearzero;
+
+  gmcoord= qh gm_matrix;
+  rows= qh gm_row;
+  FOREACHvertex_(vertices) {
+    if (vertex == notvertex)
+      continue;
+    rows[i++]= gmcoord;
+    coorda= apex;
+    coordp= vertex->point;
+    normalp= normal;
+    if (notvertex) {
+      for (k= dim; k--; )
+       *(gmcoord++)= *coordp++ - *coorda++;
+    }else {
+      dist= *offset;
+      for (k= dim; k--; )
+       dist += *coordp++ * *normalp++;
+      if (dist < -qh WIDEfacet) {
+       zinc_(Znoarea);
+       return 0.0;
+      }
+      coordp= vertex->point;
+      normalp= normal;
+      for (k= dim; k--; )
+       *(gmcoord++)= (*coordp++ - dist * *normalp++) - *coorda++;
+    }
+  }
+  if (i != dim-1) {
+    fprintf (qh ferr, "qhull internal error (qh_facetarea_simplex): #points %d != dim %d -1\n", 
+               i, dim);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  rows[i]= gmcoord;
+  if (qh DELAUNAY) {
+    for (i= 0; i < dim-1; i++)
+      rows[i][dim-1]= 0.0;
+    for (k= dim; k--; )
+      *(gmcoord++)= 0.0;
+    rows[dim-1][dim-1]= -1.0;
+  }else {
+    normalp= normal;
+    for (k= dim; k--; )
+      *(gmcoord++)= *normalp++;
+  }
+  zinc_(Zdetsimplex);
+  area= qh_determinant (rows, dim, &nearzero);
+  if (toporient)
+    area= -area;
+  area *= qh AREAfactor;
+  trace4((qh ferr, "qh_facetarea_simplex: area=%2.2g for point p%d, toporient %d, nearzero? %d\n",
+         area, qh_pointid(apex), toporient, nearzero)); 
+  return area;
+} /* facetarea_simplex */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="facetcenter">-</a>
+  
+  qh_facetcenter( vertices )
+    return Voronoi center (Voronoi vertex) for a facet's vertices
+
+  returns:
+    return temporary point equal to the center
+    
+  see:
+    qh_voronoi_center()
+*/
+pointT *qh_facetcenter (setT *vertices) {
+  setT *points= qh_settemp (qh_setsize (vertices));
+  vertexT *vertex, **vertexp;
+  pointT *center;
+  
+  FOREACHvertex_(vertices) 
+    qh_setappend (&points, vertex->point);
+  center= qh_voronoi_center (qh hull_dim-1, points);
+  qh_settempfree (&points);
+  return center;
+} /* facetcenter */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="findgooddist">-</a>
+  
+  qh_findgooddist( point, facetA, dist, facetlist )
+    find best good facet visible for point from facetA
+    assumes facetA is visible from point
+
+  returns:
+    best facet, i.e., good facet that is furthest from point
+      distance to best facet
+      NULL if none
+      
+    moves good, visible facets (and some other visible facets)
+      to end of qh facet_list
+
+  notes:
+    uses qh visit_id
+
+  design:
+    initialize bestfacet if facetA is good
+    move facetA to end of facetlist
+    for each facet on facetlist
+      for each unvisited neighbor of facet
+        move visible neighbors to end of facetlist
+        update best good neighbor
+        if no good neighbors, update best facet
+*/
+facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp, 
+               facetT **facetlist) {
+  realT bestdist= -REALmax, dist;
+  facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
+  boolT goodseen= False;  
+
+  if (facetA->good) {
+    zinc_(Zcheckpart);  /* calls from check_bestdist occur after print stats */
+    qh_distplane (point, facetA, &bestdist);
+    bestfacet= facetA;
+    goodseen= True;
+  }
+  qh_removefacet (facetA);
+  qh_appendfacet (facetA);
+  *facetlist= facetA;
+  facetA->visitid= ++qh visit_id;
+  FORALLfacet_(*facetlist) {
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == qh visit_id)
+        continue;
+      neighbor->visitid= qh visit_id;
+      if (goodseen && !neighbor->good)
+        continue;
+      zinc_(Zcheckpart); 
+      qh_distplane (point, neighbor, &dist);
+      if (dist > 0) {
+        qh_removefacet (neighbor);
+        qh_appendfacet (neighbor);
+        if (neighbor->good) {
+          goodseen= True;
+          if (dist > bestdist) {
+            bestdist= dist;
+            bestfacet= neighbor;
+          }
+        }
+      }
+    }
+  }
+  if (bestfacet) {
+    *distp= bestdist;
+    trace2((qh ferr, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
+      qh_pointid(point), bestdist, bestfacet->id));
+    return bestfacet;
+  }
+  trace4((qh ferr, "qh_findgooddist: no good facet for p%d above f%d\n", 
+      qh_pointid(point), facetA->id));
+  return NULL;
+}  /* findgooddist */
+    
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="getarea">-</a>
+  
+  qh_getarea( facetlist )
+    set area of all facets in facetlist
+    collect statistics
+
+  returns:
+    sets qh totarea/totvol to total area and volume of convex hull
+    for Delaunay triangulation, computes projected area of the lower or upper hull
+      ignores upper hull if qh ATinfinity
+  
+  notes:
+    could compute outer volume by expanding facet area by rays from interior
+    the following attempt at perpendicular projection underestimated badly:
+      qh.totoutvol += (-dist + facet->maxoutside + qh DISTround) 
+                            * area/ qh hull_dim;
+  design:
+    for each facet on facetlist
+      compute facet->area
+      update qh.totarea and qh.totvol
+*/
+void qh_getarea (facetT *facetlist) {
+  realT area;
+  realT dist;
+  facetT *facet;
+
+  if (qh REPORTfreq)
+    fprintf (qh ferr, "computing area of each facet and volume of the convex hull\n");
+  else 
+    trace1((qh ferr, "qh_getarea: computing volume and area for each facet\n"));
+  qh totarea= qh totvol= 0.0;
+  FORALLfacet_(facetlist) {
+    if (!facet->normal)
+      continue;
+    if (facet->upperdelaunay && qh ATinfinity)
+      continue;
+    facet->f.area= area= qh_facetarea (facet);
+    facet->isarea= True;
+    if (qh DELAUNAY) {
+      if (facet->upperdelaunay == qh UPPERdelaunay)
+       qh totarea += area;
+    }else {
+      qh totarea += area;
+      qh_distplane (qh interior_point, facet, &dist);
+      qh totvol += -dist * area/ qh hull_dim;
+    }
+    if (qh PRINTstatistics) {
+      wadd_(Wareatot, area);
+      wmax_(Wareamax, area);
+      wmin_(Wareamin, area);
+    }
+  }
+} /* getarea */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="gram_schmidt">-</a>
+  
+  qh_gram_schmidt( dim, row )
+    implements Gram-Schmidt orthogonalization by rows
+
+  returns:
+    false if zero norm
+    overwrites rows[dim][dim]
+
+  notes:
+    see Golub & van Loan Algorithm 6.2-2
+    overflow due to small divisors not handled
+
+  design:
+    for each row
+      compute norm for row
+      if non-zero, normalize row
+      for each remaining rowA
+        compute inner product of row and rowA
+        reduce rowA by row * inner product
+*/
+boolT qh_gram_schmidt(int dim, realT **row) {
+  realT *rowi, *rowj, norm;
+  int i, j, k;
+  
+  for(i=0; i < dim; i++) {
+    rowi= row[i];
+    for (norm= 0.0, k= dim; k--; rowi++)
+      norm += *rowi * *rowi;
+    norm= sqrt(norm);
+    wmin_(Wmindenom, norm);
+    if (norm == 0.0)  /* either 0 or overflow due to sqrt */
+      return False;
+    for(k= dim; k--; )
+      *(--rowi) /= norm;  
+    for(j= i+1; j < dim; j++) {
+      rowj= row[j];
+      for(norm= 0.0, k=dim; k--; )
+       norm += *rowi++ * *rowj++;
+      for(k=dim; k--; )
+       *(--rowj) -= *(--rowi) * norm;
+    }
+  }
+  return True;
+} /* gram_schmidt */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="inthresholds">-</a>
+  
+  qh_inthresholds( normal, angle )
+    return True if normal within qh.lower_/upper_threshold
+
+  returns:
+    estimate of angle by summing of threshold diffs
+      angle may be NULL
+      smaller "angle" is better
+  
+  notes:
+    invalid if qh.SPLITthresholds
+
+  see:
+    qh.lower_threshold in qh_initbuild()
+    qh_initthresholds()
+
+  design:
+    for each dimension
+      test threshold
+*/
+boolT qh_inthresholds (coordT *normal, realT *angle) {
+  boolT within= True;
+  int k;
+  realT threshold;
+
+  if (angle)
+    *angle= 0.0;
+  for(k= 0; k < qh hull_dim; k++) {
+    threshold= qh lower_threshold[k];
+    if (threshold > -REALmax/2) {
+      if (normal[k] < threshold)
+        within= False;
+      if (angle) {
+       threshold -= normal[k];
+       *angle += fabs_(threshold);
+      }
+    }
+    if (qh upper_threshold[k] < REALmax/2) {
+      threshold= qh upper_threshold[k];
+      if (normal[k] > threshold)
+        within= False;
+      if (angle) {
+       threshold -= normal[k];
+       *angle += fabs_(threshold);
+      }
+    }
+  }
+  return within;
+} /* inthresholds */
+    
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="joggleinput">-</a>
+  
+  qh_joggleinput()
+    randomly joggle input to Qhull by qh.JOGGLEmax
+    initial input is qh.first_point/qh.num_points of qh.hull_dim
+      repeated calls use qh.input_points/qh.num_points
+  returns:
+    joggles points at qh.first_point/qh.num_points
+    copies data to qh.input_points/qh.input_malloc if first time
+    determines qh.JOGGLEmax if it was zero
+    if qh.DELAUNAY
+      computes the Delaunay projection of the joggled points
+
+  notes:
+    if qh.DELAUNAY, unnecessarily joggles the last coordinate
+    the initial 'QJn' may be set larger than qh_JOGGLEmaxincrease
+
+  design:
+    if qh.DELAUNAY
+      set qh.SCALElast for reduced precision errors
+    if first call
+      initialize qh.input_points to the original input points
+      if qh.JOGGLEmax == 0
+        determine default qh.JOGGLEmax
+    else
+      increase qh.JOGGLEmax according to qh.build_cnt
+    joggle the input by adding a random number in [-qh.JOGGLEmax,qh.JOGGLEmax]
+    if qh.DELAUNAY
+      sets the Delaunay projection
+*/
+void qh_joggleinput (void) {
+  int size, i, seed;
+  coordT *coordp, *inputp;
+  realT randr, randa, randb;
+
+  if (!qh input_points) { /* first call */
+    qh input_points= qh first_point;
+    qh input_malloc= qh POINTSmalloc;
+    size= qh num_points * qh hull_dim * sizeof(coordT);
+    if (!(qh first_point=(coordT*)malloc(size))) {
+      fprintf(qh ferr, "qhull error: insufficient memory to joggle %d points\n",
+          qh num_points);
+      qh_errexit(qh_ERRmem, NULL, NULL);
+    }
+    qh POINTSmalloc= True;
+    if (qh JOGGLEmax == 0.0) {
+      qh JOGGLEmax= qh_detjoggle (qh input_points, qh num_points, qh hull_dim);
+      qh_option ("QJoggle", NULL, &qh JOGGLEmax);
+    }
+  }else {                 /* repeated call */
+    if (!qh RERUN && qh build_cnt > qh_JOGGLEretry) {
+      if (((qh build_cnt-qh_JOGGLEretry-1) % qh_JOGGLEagain) == 0) {
+       realT maxjoggle= qh MAXwidth * qh_JOGGLEmaxincrease;
+       if (qh JOGGLEmax < maxjoggle) {
+         qh JOGGLEmax *= qh_JOGGLEincrease;
+         minimize_(qh JOGGLEmax, maxjoggle); 
+       }
+      }
+    }
+    qh_option ("QJoggle", NULL, &qh JOGGLEmax);
+  }
+  if (qh build_cnt > 1 && qh JOGGLEmax > fmax_(qh MAXwidth/4, 0.1)) {
+      fprintf (qh ferr, "qhull error: the current joggle for 'QJn', %.2g, is too large for the width\nof the input.  If possible, recompile Qhull with higher-precision reals.\n",
+               qh JOGGLEmax);
+      qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  /* for some reason, using qh ROTATErandom and qh_RANDOMseed does not repeat the run. Use 'TRn' instead */
+  seed= qh_RANDOMint;
+  qh_option ("_joggle-seed", &seed, NULL);
+  trace0((qh ferr, "qh_joggleinput: joggle input by %2.2g with seed %d\n", 
+    qh JOGGLEmax, seed));
+  inputp= qh input_points;
+  coordp= qh first_point;
+  randa= 2.0 * qh JOGGLEmax/qh_RANDOMmax;
+  randb= -qh JOGGLEmax;
+  size= qh num_points * qh hull_dim;
+  for (i= size; i--; ) {
+    randr= qh_RANDOMint;
+    *(coordp++)= *(inputp++) + (randr * randa + randb);
+  }
+  if (qh DELAUNAY) {
+    qh last_low= qh last_high= qh last_newhigh= REALmax;
+    qh_setdelaunay (qh hull_dim, qh num_points, qh first_point);
+  }
+} /* joggleinput */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="maxabsval">-</a>
+  
+  qh_maxabsval( normal, dim )
+    return pointer to maximum absolute value of a dim vector
+    returns NULL if dim=0
+*/
+realT *qh_maxabsval (realT *normal, int dim) {
+  realT maxval= -REALmax;
+  realT *maxp= NULL, *colp, absval;
+  int k;
+
+  for (k= dim, colp= normal; k--; colp++) {
+    absval= fabs_(*colp);
+    if (absval > maxval) {
+      maxval= absval;
+      maxp= colp;
+    }
+  }
+  return maxp;
+} /* maxabsval */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="maxmin">-</a>
+  
+  qh_maxmin( points, numpoints, dimension )
+    return max/min points for each dimension      
+    determine max and min coordinates
+
+  returns:
+    returns a temporary set of max and min points
+      may include duplicate points. Does not include qh.GOODpoint
+    sets qh.NEARzero, qh.MAXabs_coord, qh.MAXsumcoord, qh.MAXwidth
+         qh.MAXlastcoord, qh.MINlastcoord
+    initializes qh.max_outside, qh.min_vertex, qh.WAScoplanar, qh.ZEROall_ok
+
+  notes:
+    loop duplicated in qh_detjoggle()
+
+  design:
+    initialize global precision variables
+    checks definition of REAL...
+    for each dimension
+      for each point
+        collect maximum and minimum point
+      collect maximum of maximums and minimum of minimums
+      determine qh.NEARzero for Gaussian Elimination
+*/
+setT *qh_maxmin(pointT *points, int numpoints, int dimension) {
+  int k;
+  realT maxcoord, temp;
+  pointT *minimum, *maximum, *point, *pointtemp;
+  setT *set;
+
+  qh max_outside= 0.0;
+  qh MAXabs_coord= 0.0;
+  qh MAXwidth= -REALmax;
+  qh MAXsumcoord= 0.0;
+  qh min_vertex= 0.0;
+  qh WAScoplanar= False;
+  if (qh ZEROcentrum)
+    qh ZEROall_ok= True;
+  if (REALmin < REALepsilon && REALmin < REALmax && REALmin > -REALmax
+  && REALmax > 0.0 && -REALmax < 0.0)
+    ; /* all ok */
+  else {
+    fprintf (qh ferr, "qhull error: floating point constants in user.h are wrong\n\
+REALepsilon %g REALmin %g REALmax %g -REALmax %g\n",
+            REALepsilon, REALmin, REALmax, -REALmax);
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  set= qh_settemp(2*dimension);
+  for(k= 0; k < dimension; k++) {
+    if (points == qh GOODpointp)
+      minimum= maximum= points + dimension;
+    else
+      minimum= maximum= points;
+    FORALLpoint_(points, numpoints) {
+      if (point == qh GOODpointp)
+       continue;
+      if (maximum[k] < point[k])
+       maximum= point;
+      else if (minimum[k] > point[k])
+       minimum= point;
+    }
+    if (k == dimension-1) {
+      qh MINlastcoord= minimum[k];
+      qh MAXlastcoord= maximum[k];
+    }
+    if (qh SCALElast && k == dimension-1)
+      maxcoord= qh MAXwidth;
+    else {
+      maxcoord= fmax_(maximum[k], -minimum[k]);
+      if (qh GOODpointp) {
+        temp= fmax_(qh GOODpointp[k], -qh GOODpointp[k]);
+        maximize_(maxcoord, temp);
+      }
+      temp= maximum[k] - minimum[k];
+      maximize_(qh MAXwidth, temp);
+    }
+    maximize_(qh MAXabs_coord, maxcoord);
+    qh MAXsumcoord += maxcoord;
+    qh_setappend (&set, maximum);
+    qh_setappend (&set, minimum);
+    /* calculation of qh NEARzero is based on error formula 4.4-13 of
+       Golub & van Loan, authors say n^3 can be ignored and 10 be used in
+       place of rho */
+    qh NEARzero[k]= 80 * qh MAXsumcoord * REALepsilon;
+  }
+  if (qh IStracing >=1)
+    qh_printpoints (qh ferr, "qh_maxmin: found the max and min points (by dim):", set);
+  return(set);
+} /* maxmin */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="maxouter">-</a>
+
+  qh_maxouter()
+    return maximum distance from facet to outer plane
+    normally this is qh.max_outside+qh.DISTround
+    does not include qh.JOGGLEmax
+
+  see:
+    qh_outerinner()
+    
+  notes:
+    need to add another qh.DISTround if testing actual point with computation
+
+  for joggle:
+    qh_setfacetplane() updated qh.max_outer for Wnewvertexmax (max distance to vertex)
+    need to use Wnewvertexmax since could have a coplanar point for a high 
+      facet that is replaced by a low facet
+    need to add qh.JOGGLEmax if testing input points
+*/
+realT qh_maxouter (void) {
+  realT dist;
+
+  dist= fmax_(qh max_outside, qh DISTround);
+  dist += qh DISTround;
+  trace4((qh ferr, "qh_maxouter: max distance from facet to outer plane is %2.2g max_outside is %2.2g\n", dist, qh max_outside));
+  return dist;
+} /* maxouter */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="maxsimplex">-</a>
+  
+  qh_maxsimplex( dim, maxpoints, points, numpoints, simplex )
+    determines maximum simplex for a set of points 
+    starts from points already in simplex
+    skips qh.GOODpointp (assumes that it isn't in maxpoints)
+  
+  returns:
+    simplex with dim+1 points
+
+  notes:
+    assumes at least pointsneeded points in points
+    maximizes determinate for x,y,z,w, etc.
+    uses maxpoints as long as determinate is clearly non-zero
+
+  design:
+    initialize simplex with at least two points
+      (find points with max or min x coordinate)
+    for each remaining dimension
+      add point that maximizes the determinate
+        (use points from maxpoints first)    
+*/
+void qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
+  pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
+  boolT nearzero, maxnearzero= False;
+  int k, sizinit;
+  realT maxdet= -REALmax, det, mincoord= REALmax, maxcoord= -REALmax;
+
+  sizinit= qh_setsize (*simplex);
+  if (sizinit < 2) {
+    if (qh_setsize (maxpoints) >= 2) {
+      FOREACHpoint_(maxpoints) {
+        if (maxcoord < point[0]) {
+          maxcoord= point[0];
+          maxx= point;
+        }
+       if (mincoord > point[0]) {
+          mincoord= point[0];
+          minx= point;
+        }
+      }
+    }else {
+      FORALLpoint_(points, numpoints) {
+       if (point == qh GOODpointp)
+         continue;
+        if (maxcoord < point[0]) {
+         maxcoord= point[0];
+          maxx= point;
+        }
+       if (mincoord > point[0]) {
+          mincoord= point[0];
+          minx= point;
+       }
+      }
+    }
+    qh_setunique (simplex, minx);
+    if (qh_setsize (*simplex) < 2)
+      qh_setunique (simplex, maxx);
+    sizinit= qh_setsize (*simplex);
+    if (sizinit < 2) {
+      qh_precision ("input has same x coordinate");
+      if (zzval_(Zsetplane) > qh hull_dim+1) {
+       fprintf (qh ferr, "qhull precision error (qh_maxsimplex for voronoi_center):\n%d points with the same x coordinate.\n",
+                qh_setsize(maxpoints)+numpoints);
+       qh_errexit (qh_ERRprec, NULL, NULL);
+      }else {
+       fprintf (qh ferr, "qhull input error: input is less than %d-dimensional since it has the same x coordinate\n", qh hull_dim);
+       qh_errexit (qh_ERRinput, NULL, NULL);
+      }
+    }
+  }
+  for(k= sizinit; k < dim+1; k++) {
+    maxpoint= NULL;
+    maxdet= -REALmax;
+    FOREACHpoint_(maxpoints) {
+      if (!qh_setin (*simplex, point)) {
+        det= qh_detsimplex(point, *simplex, k, &nearzero);
+        if ((det= fabs_(det)) > maxdet) {
+         maxdet= det;
+          maxpoint= point;
+         maxnearzero= nearzero;
+        }
+      }
+    }
+    if (!maxpoint || maxnearzero) {
+      zinc_(Zsearchpoints);
+      if (!maxpoint) {
+        trace0((qh ferr, "qh_maxsimplex: searching all points for %d-th initial vertex.\n", k+1));
+      }else {
+        trace0((qh ferr, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g\n",
+               k+1, qh_pointid(maxpoint), maxdet));
+      }
+      FORALLpoint_(points, numpoints) {
+       if (point == qh GOODpointp)
+         continue;
+        if (!qh_setin (*simplex, point)) {
+          det= qh_detsimplex(point, *simplex, k, &nearzero);
+          if ((det= fabs_(det)) > maxdet) {
+           maxdet= det;
+            maxpoint= point;
+           maxnearzero= nearzero;
+         }
+        }
+      }
+    } /* !maxpoint */
+    if (!maxpoint) {
+      fprintf (qh ferr, "qhull internal error (qh_maxsimplex): not enough points available\n");
+      qh_errexit (qh_ERRqhull, NULL, NULL);
+    }
+    qh_setappend(simplex, maxpoint);
+    trace1((qh ferr, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%2.2g\n",
+           qh_pointid(maxpoint), k+1, maxdet));
+  } /* k */ 
+} /* maxsimplex */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="minabsval">-</a>
+  
+  qh_minabsval( normal, dim )
+    return minimum absolute value of a dim vector
+*/
+realT qh_minabsval (realT *normal, int dim) {
+  realT minval= 0;
+  realT maxval= 0;
+  realT *colp;
+  int k;
+
+  for (k= dim, colp= normal; k--; colp++) {
+    maximize_(maxval, *colp);
+    minimize_(minval, *colp);
+  }
+  return fmax_(maxval, -minval);
+} /* minabsval */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="mindiff">-</a>
+  
+  qh_mindif( vecA, vecB, dim )
+    return index of min abs. difference of two vectors
+*/
+int qh_mindiff (realT *vecA, realT *vecB, int dim) {
+  realT mindiff= REALmax, diff;
+  realT *vecAp= vecA, *vecBp= vecB;
+  int k, mink= 0;
+
+  for (k= 0; k < dim; k++) {
+    diff= *vecAp++ - *vecBp++;
+    diff= fabs_(diff);
+    if (diff < mindiff) {
+      mindiff= diff;
+      mink= k;
+    }
+  }
+  return mink;
+} /* mindiff */
+
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="orientoutside">-</a>
+  
+  qh_orientoutside( facet  )
+    make facet outside oriented via qh.interior_point
+
+  returns:
+    True if facet reversed orientation.
+*/
+boolT qh_orientoutside (facetT *facet) {
+  int k;
+  realT dist;
+
+  qh_distplane (qh interior_point, facet, &dist);
+  if (dist > 0) {
+    for (k= qh hull_dim; k--; )
+      facet->normal[k]= -facet->normal[k];
+    facet->offset= -facet->offset;
+    return True;
+  }
+  return False;
+} /* orientoutside */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="outerinner">-</a>
+  
+  qh_outerinner( facet, outerplane, innerplane  )
+    if facet and qh.maxoutdone (i.e., qh_check_maxout)
+      returns outer and inner plane for facet
+    else
+      returns maximum outer and inner plane
+    accounts for qh.JOGGLEmax
+
+  see:
+    qh_maxouter(), qh_check_bestdist(), qh_check_points()
+
+  notes:
+    outerplaner or innerplane may be NULL
+    
+    includes qh.DISTround for actual points
+    adds another qh.DISTround if testing with floating point arithmetic
+*/
+void qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane) {
+  realT dist, mindist;
+  vertexT *vertex, **vertexp;
+
+  if (outerplane) {
+    if (!qh_MAXoutside || !facet || !qh maxoutdone) {
+      *outerplane= qh_maxouter();       /* includes qh.DISTround */
+    }else { /* qh_MAXoutside ... */
+#if qh_MAXoutside 
+      *outerplane= facet->maxoutside + qh DISTround;
+#endif
+      
+    }
+    if (qh JOGGLEmax < REALmax/2)
+      *outerplane += qh JOGGLEmax * sqrt (qh hull_dim);
+  }
+  if (innerplane) {
+    if (facet) {
+      mindist= REALmax;
+      FOREACHvertex_(facet->vertices) {
+        zinc_(Zdistio);
+        qh_distplane (vertex->point, facet, &dist);
+        minimize_(mindist, dist);
+      }
+      *innerplane= mindist - qh DISTround;
+    }else 
+      *innerplane= qh min_vertex - qh DISTround;
+    if (qh JOGGLEmax < REALmax/2)
+      *innerplane -= qh JOGGLEmax * sqrt (qh hull_dim);
+  }
+} /* outerinner */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="pointdist">-</a>
+  
+  qh_pointdist( point1, point2, dim )
+    return distance between two points
+
+  notes:
+    returns distance squared if 'dim' is negative
+*/
+coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
+  coordT dist, diff;
+  int k;
+  
+  dist= 0.0;
+  for (k= (dim > 0 ? dim : -dim); k--; ) {
+    diff= *point1++ - *point2++;
+    dist += diff * diff;
+  }
+  if (dim > 0)
+    return(sqrt(dist));
+  return dist;
+} /* pointdist */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="printmatrix">-</a>
+  
+  qh_printmatrix( fp, string, rows, numrow, numcol )
+    print matrix to fp given by row vectors
+    print string as header
+
+  notes:
+    print a vector by qh_printmatrix(fp, "", &vect, 1, len)
+*/
+void qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol) {
+  realT *rowp;
+  realT r; /*bug fix*/
+  int i,k;
+
+  fprintf (fp, "%s\n", string);
+  for (i= 0; i < numrow; i++) {
+    rowp= rows[i];
+    for (k= 0; k < numcol; k++) {
+      r= *rowp++;
+      fprintf (fp, "%6.3g ", r);
+    }
+    fprintf (fp, "\n");
+  }
+} /* printmatrix */
+
+  
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="printpoints">-</a>
+  
+  qh_printpoints( fp, string, points )
+    print pointids to fp for a set of points
+    if string, prints string and 'p' point ids
+*/
+void qh_printpoints (FILE *fp, char *string, setT *points) {
+  pointT *point, **pointp;
+
+  if (string) {
+    fprintf (fp, "%s", string);
+    FOREACHpoint_(points) 
+      fprintf (fp, " p%d", qh_pointid(point));
+    fprintf (fp, "\n");
+  }else {
+    FOREACHpoint_(points) 
+      fprintf (fp, " %d", qh_pointid(point));
+    fprintf (fp, "\n");
+  }
+} /* printpoints */
+
+  
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="projectinput">-</a>
+  
+  qh_projectinput()
+    project input points using qh.lower_bound/upper_bound and qh DELAUNAY
+    if qh.lower_bound[k]=qh.upper_bound[k]= 0, 
+      removes dimension k 
+    if halfspace intersection
+      removes dimension k from qh.feasible_point
+    input points in qh first_point, num_points, input_dim
+
+  returns:
+    new point array in qh first_point of qh hull_dim coordinates
+    sets qh POINTSmalloc
+    if qh DELAUNAY 
+      projects points to paraboloid
+      lowbound/highbound is also projected
+    if qh ATinfinity
+      adds point "at-infinity"
+    if qh POINTSmalloc 
+      frees old point array
+
+  notes:
+    checks that qh.hull_dim agrees with qh.input_dim, PROJECTinput, and DELAUNAY
+
+
+  design:
+    sets project[k] to -1 (delete), 0 (keep), 1 (add for Delaunay)
+    determines newdim and newnum for qh hull_dim and qh num_points
+    projects points to newpoints
+    projects qh.lower_bound to itself
+    projects qh.upper_bound to itself
+    if qh DELAUNAY
+      if qh ATINFINITY
+        projects points to paraboloid
+        computes "infinity" point as vertex average and 10% above all points 
+      else
+        uses qh_setdelaunay to project points to paraboloid
+*/
+void qh_projectinput (void) {
+  int k,i;
+  int newdim= qh input_dim, newnum= qh num_points;
+  signed char *project;
+  int size= (qh input_dim+1)*sizeof(*project);
+  pointT *newpoints, *coord, *infinity;
+  realT paraboloid, maxboloid= 0;
+  
+  project= (signed char*)qh_memalloc (size);
+  memset ((char*)project, 0, size);
+  for (k= 0; k < qh input_dim; k++) {   /* skip Delaunay bound */
+    if (qh lower_bound[k] == 0 && qh upper_bound[k] == 0) {
+      project[k]= -1;
+      newdim--;
+    }
+  }
+  if (qh DELAUNAY) {
+    project[k]= 1;
+    newdim++;
+    if (qh ATinfinity)
+      newnum++;
+  }
+  if (newdim != qh hull_dim) {
+    fprintf(qh ferr, "qhull internal error (qh_projectinput): dimension after projection %d != hull_dim %d\n", newdim, qh hull_dim);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (!(newpoints=(coordT*)malloc(newnum*newdim*sizeof(coordT)))){
+    fprintf(qh ferr, "qhull error: insufficient memory to project %d points\n",
+           qh num_points);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  qh_projectpoints (project, qh input_dim+1, qh first_point,
+                    qh num_points, qh input_dim, newpoints, newdim);
+  trace1((qh ferr, "qh_projectinput: updating lower and upper_bound\n"));
+  qh_projectpoints (project, qh input_dim+1, qh lower_bound,
+                    1, qh input_dim+1, qh lower_bound, newdim+1);
+  qh_projectpoints (project, qh input_dim+1, qh upper_bound,
+                    1, qh input_dim+1, qh upper_bound, newdim+1);
+  if (qh HALFspace) {
+    if (!qh feasible_point) {
+      fprintf(qh ferr, "qhull internal error (qh_projectinput): HALFspace defined without qh.feasible_point\n");
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+    }
+    qh_projectpoints (project, qh input_dim, qh feasible_point,
+                     1, qh input_dim, qh feasible_point, newdim);
+  }
+  qh_memfree(project, ((qh input_dim+1)*sizeof(*project)));
+  if (qh POINTSmalloc)
+    free (qh first_point);
+  qh first_point= newpoints;
+  qh POINTSmalloc= True;
+  if (qh DELAUNAY && qh ATinfinity) {
+    coord= qh first_point;
+    infinity= qh first_point + qh hull_dim * qh num_points;
+    for (k=qh hull_dim-1; k--; )
+      infinity[k]= 0.0;
+    for (i=qh num_points; i--; ) {
+      paraboloid= 0.0;
+      for (k=qh hull_dim-1; k--; ) {
+        paraboloid += *coord * *coord;
+       infinity[k] += *coord;
+        coord++;
+      }
+      *(coord++)= paraboloid;
+      maximize_(maxboloid, paraboloid);
+    }
+    /* coord == infinity */
+    for (k=qh hull_dim-1; k--; )
+      *(coord++) /= qh num_points;
+    *(coord++)= maxboloid * 1.1;
+    qh num_points++;
+    trace0((qh ferr, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
+  }else if (qh DELAUNAY)  /* !qh ATinfinity */
+    qh_setdelaunay( qh hull_dim, qh num_points, qh first_point);
+} /* projectinput */
+
+  
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="projectpoints">-</a>
+  
+  qh_projectpoints( project, n, points, numpoints, dim, newpoints, newdim )
+    project points/numpoints/dim to newpoints/newdim
+    if project[k] == -1
+      delete dimension k 
+    if project[k] == 1 
+      add dimension k by duplicating previous column
+    n is size of project
+
+  notes:
+    newpoints may be points if only adding dimension at end
+
+  design:
+    check that 'project' and 'newdim' agree
+    for each dimension
+      if project == -1
+        skip dimension
+      else
+        determine start of column in newpoints
+        determine start of column in points 
+          if project == +1, duplicate previous column
+        copy dimension (column) from points to newpoints
+*/
+void qh_projectpoints (signed char *project, int n, realT *points, 
+        int numpoints, int dim, realT *newpoints, int newdim) {
+  int testdim= dim, oldk=0, newk=0, i,j=0,k;
+  realT *newp, *oldp;
+  
+  for (k= 0; k < n; k++)
+    testdim += project[k];
+  if (testdim != newdim) {
+    fprintf (qh ferr, "qhull internal error (qh_projectpoints): newdim %d should be %d after projection\n",
+      newdim, testdim);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  for (j= 0; j<n; j++) {
+    if (project[j] == -1)
+      oldk++;
+    else {
+      newp= newpoints+newk++;
+      if (project[j] == +1) {
+       if (oldk >= dim)
+         continue;
+       oldp= points+oldk;
+      }else 
+       oldp= points+oldk++;
+      for (i=numpoints; i--; ) {
+        *newp= *oldp;
+        newp += newdim;
+        oldp += dim;
+      }
+    }
+    if (oldk >= dim)
+      break;
+  }
+  trace1((qh ferr, "qh_projectpoints: projected %d points from dim %d to dim %d\n", 
+    numpoints, dim, newdim));
+} /* projectpoints */
+        
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="rand">-</a>
+  
+  qh_rand() 
+  qh_srand( seed )
+    generate pseudo-random number between 1 and 2^31 -2
+
+  notes:
+    from Park & Miller's minimimal standard random number generator
+       Communications of the ACM, 31:1192-1201, 1988.
+    does not use 0 or 2^31 -1
+       this is silently enforced by qh_srand()
+    can make 'Rn' much faster by moving qh_rand to qh_distplane
+*/
+int qh_rand_seed= 1;  /* define as global variable instead of using qh */
+
+int qh_rand( void) {
+#define qh_rand_a 16807
+#define qh_rand_m 2147483647
+#define qh_rand_q 127773  /* m div a */
+#define qh_rand_r 2836    /* m mod a */
+  int lo, hi, test;
+  int seed = qh_rand_seed;
+
+  hi = seed / qh_rand_q;  /* seed div q */
+  lo = seed % qh_rand_q;  /* seed mod q */
+  test = qh_rand_a * lo - qh_rand_r * hi;
+  if (test > 0)
+    seed= test;
+  else
+    seed= test + qh_rand_m;
+  qh_rand_seed= seed;
+  /* seed = seed < qh_RANDOMmax/2 ? 0 : qh_RANDOMmax;  for testing */
+  /* seed = qh_RANDOMmax;  for testing */
+  return seed;
+} /* rand */
+
+void qh_srand( int seed) {
+  if (seed < 1)
+    qh_rand_seed= 1;
+  else if (seed >= qh_rand_m)
+    qh_rand_seed= qh_rand_m - 1;
+  else
+    qh_rand_seed= seed;
+} /* qh_srand */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="randomfactor">-</a>
+  
+  qh_randomfactor()
+    return a random factor within qh.RANDOMmax of 1.0
+
+  notes:
+    qh.RANDOMa/b are defined in global.c
+*/
+realT qh_randomfactor (void) {
+  realT randr;
+
+  randr= qh_RANDOMint;
+  return randr * qh RANDOMa + qh RANDOMb;
+} /* randomfactor */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="randommatrix">-</a>
+  
+  qh_randommatrix( buffer, dim, rows )
+    generate a random dim X dim matrix in range [-1,1]
+    assumes buffer is [dim+1, dim]
+
+  returns:
+    sets buffer to random numbers
+    sets rows to rows of buffer
+      sets row[dim] as scratch row
+*/
+void qh_randommatrix (realT *buffer, int dim, realT **rows) {
+  int i, k;
+  realT **rowi, *coord, realr;
+
+  coord= buffer;
+  rowi= rows;
+  for (i=0; i < dim; i++) {
+    *(rowi++)= coord;
+    for (k=0; k < dim; k++) {
+      realr= qh_RANDOMint;
+      *(coord++)= 2.0 * realr/(qh_RANDOMmax+1) - 1.0;
+    }
+  }
+  *rowi= coord;
+} /* randommatrix */
+
+        
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="rotateinput">-</a>
+  
+  qh_rotateinput( rows )
+    rotate input using row matrix
+    input points given by qh first_point, num_points, hull_dim
+    assumes rows[dim] is a scratch buffer
+    if qh POINTSmalloc, overwrites input points, else mallocs a new array
+
+  returns:
+    rotated input
+    sets qh POINTSmalloc
+
+  design:
+    see qh_rotatepoints
+*/
+void qh_rotateinput (realT **rows) {
+
+  if (!qh POINTSmalloc) {
+    qh first_point= qh_copypoints (qh first_point, qh num_points, qh hull_dim);
+    qh POINTSmalloc= True;
+  }
+  qh_rotatepoints (qh first_point, qh num_points, qh hull_dim, rows);
+}  /* rotateinput */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="rotatepoints">-</a>
+  
+  qh_rotatepoints( points, numpoints, dim, row )
+    rotate numpoints points by a d-dim row matrix
+    assumes rows[dim] is a scratch buffer
+
+  returns:
+    rotated points in place
+
+  design:
+    for each point
+      for each coordinate
+        use row[dim] to compute partial inner product
+      for each coordinate
+        rotate by partial inner product
+*/
+void qh_rotatepoints (realT *points, int numpoints, int dim, realT **row) {
+  realT *point, *rowi, *coord= NULL, sum, *newval;
+  int i,j,k;
+
+  if (qh IStracing >= 1)
+    qh_printmatrix (qh ferr, "qh_rotatepoints: rotate points by", row, dim, dim);
+  for (point= points, j= numpoints; j--; point += dim) {
+    newval= row[dim];
+    for (i= 0; i < dim; i++) {
+      rowi= row[i];
+      coord= point;
+      for (sum= 0.0, k= dim; k--; )
+        sum += *rowi++ * *coord++;
+      *(newval++)= sum;
+    }
+    for (k= dim; k--; )
+      *(--coord)= *(--newval);
+  }
+} /* rotatepoints */  
+  
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="scaleinput">-</a>
+  
+  qh_scaleinput()
+    scale input points using qh low_bound/high_bound
+    input points given by qh first_point, num_points, hull_dim
+    if qh POINTSmalloc, overwrites input points, else mallocs a new array
+
+  returns:
+    scales coordinates of points to low_bound[k], high_bound[k]
+    sets qh POINTSmalloc
+
+  design:
+    see qh_scalepoints
+*/
+void qh_scaleinput (void) {
+
+  if (!qh POINTSmalloc) {
+    qh first_point= qh_copypoints (qh first_point, qh num_points, qh hull_dim);
+    qh POINTSmalloc= True;
+  }
+  qh_scalepoints (qh first_point, qh num_points, qh hull_dim,
+       qh lower_bound, qh upper_bound);
+}  /* scaleinput */
+  
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="scalelast">-</a>
+  
+  qh_scalelast( points, numpoints, dim, low, high, newhigh )
+    scale last coordinate to [0,m] for Delaunay triangulations
+    input points given by points, numpoints, dim
+
+  returns:
+    changes scale of last coordinate from [low, high] to [0, newhigh]
+    overwrites last coordinate of each point
+    saves low/high/newhigh in qh.last_low, etc. for qh_setdelaunay()
+
+  notes:
+    when called by qh_setdelaunay, low/high may not match actual data
+    
+  design:
+    compute scale and shift factors
+    apply to last coordinate of each point
+*/
+void qh_scalelast (coordT *points, int numpoints, int dim, coordT low,
+                  coordT high, coordT newhigh) {
+  realT scale, shift;
+  coordT *coord;
+  int i;
+  boolT nearzero= False;
+
+  trace4((qh ferr, "qh_scalelast: scale last coordinate from [%2.2g, %2.2g] to [0,%2.2g]\n",
+    low, high, newhigh));
+  qh last_low= low;
+  qh last_high= high;
+  qh last_newhigh= newhigh;
+  scale= qh_divzero (newhigh, high - low,
+                  qh MINdenom_1, &nearzero);
+  if (nearzero) {
+    if (qh DELAUNAY)
+      fprintf (qh ferr, "qhull input error: can not scale last coordinate.  Input is cocircular\n   or cospherical.   Use option 'Qz' to add a point at infinity.\n");
+    else
+      fprintf (qh ferr, "qhull input error: can not scale last coordinate.  New bounds [0, %2.2g] are too wide for\nexisting bounds [%2.2g, %2.2g] (width %2.2g)\n",
+               newhigh, low, high, high-low);
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  shift= - low * newhigh / (high-low);
+  coord= points + dim - 1;
+  for (i= numpoints; i--; coord += dim)
+    *coord= *coord * scale + shift;
+} /* scalelast */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="scalepoints">-</a>
+  
+  qh_scalepoints( points, numpoints, dim, newlows, newhighs )
+    scale points to new lowbound and highbound
+    retains old bound when newlow= -REALmax or newhigh= +REALmax
+
+  returns:
+    scaled points
+    overwrites old points
+
+  design:
+    for each coordinate
+      compute current low and high bound
+      compute scale and shift factors
+      scale all points
+      enforce new low and high bound for all points
+*/
+void qh_scalepoints (pointT *points, int numpoints, int dim,
+       realT *newlows, realT *newhighs) {
+  int i,k;
+  realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
+  boolT nearzero= False;
+     
+  for (k= 0; k < dim; k++) {
+    newhigh= newhighs[k];
+    newlow= newlows[k];
+    if (newhigh > REALmax/2 && newlow < -REALmax/2)
+      continue;
+    low= REALmax;
+    high= -REALmax;
+    for (i= numpoints, coord= points+k; i--; coord += dim) {
+      minimize_(low, *coord);
+      maximize_(high, *coord);
+    }
+    if (newhigh > REALmax/2)
+      newhigh= high;
+    if (newlow < -REALmax/2)
+      newlow= low;
+    if (qh DELAUNAY && k == dim-1 && newhigh < newlow) {
+      fprintf (qh ferr, "qhull input error: 'Qb%d' or 'QB%d' inverts paraboloid since high bound %.2g < low bound %.2g\n",
+              k, k, newhigh, newlow);
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+    scale= qh_divzero (newhigh - newlow, high - low,
+                  qh MINdenom_1, &nearzero);
+    if (nearzero) {
+      fprintf (qh ferr, "qhull input error: %d'th dimension's new bounds [%2.2g, %2.2g] too wide for\nexisting bounds [%2.2g, %2.2g]\n",
+              k, newlow, newhigh, low, high);
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+    shift= (newlow * high - low * newhigh)/(high-low);
+    coord= points+k;
+    for (i= numpoints; i--; coord += dim)
+      *coord= *coord * scale + shift;
+    coord= points+k;
+    if (newlow < newhigh) {
+      mincoord= newlow;
+      maxcoord= newhigh;
+    }else {
+      mincoord= newhigh;
+      maxcoord= newlow;
+    }
+    for (i= numpoints; i--; coord += dim) {
+      minimize_(*coord, maxcoord);  /* because of roundoff error */
+      maximize_(*coord, mincoord);
+    }
+    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",
+      k, low, high, newlow, newhigh, numpoints, scale, shift));
+  }
+} /* scalepoints */    
+
+       
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="setdelaunay">-</a>
+  
+  qh_setdelaunay( dim, count, points )
+    project count points to dim-d paraboloid for Delaunay triangulation
+    
+    dim is one more than the dimension of the input set
+    assumes dim is at least 3 (i.e., at least a 2-d Delaunay triangulation)
+
+    points is a dim*count realT array.  The first dim-1 coordinates
+    are the coordinates of the first input point.  array[dim] is
+    the first coordinate of the second input point.  array[2*dim] is
+    the first coordinate of the third input point.
+
+    if qh.last_low defined (i.e., 'Qbb' called qh_scalelast)
+      calls qh_scalelast to scale the last coordinate the same as the other points
+
+  returns:
+    for each point
+      sets point[dim-1] to sum of squares of coordinates
+    scale points to 'Qbb' if needed
+      
+  notes:
+    to project one point, use
+      qh_setdelaunay (qh hull_dim, 1, point)
+      
+    Do not use options 'Qbk', 'QBk', or 'QbB' since they scale 
+    the coordinates after the original projection.
+
+*/
+void qh_setdelaunay (int dim, int count, pointT *points) {
+  int i, k;
+  coordT *coordp, coord;
+  realT paraboloid;
+
+  trace0((qh ferr, "qh_setdelaunay: project %d points to paraboloid for Delaunay triangulation\n", count));
+  coordp= points;
+  for (i= 0; i < count; i++) {
+    coord= *coordp++;
+    paraboloid= coord*coord;
+    for (k= dim-2; k--; ) {
+      coord= *coordp++;
+      paraboloid += coord*coord;
+    }
+    *coordp++ = paraboloid;
+  }
+  if (qh last_low < REALmax/2) 
+    qh_scalelast (points, count, dim, qh last_low, qh last_high, qh last_newhigh);
+} /* setdelaunay */
+
+  
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sethalfspace">-</a>
+  
+  qh_sethalfspace( dim, coords, nextp, normal, offset, feasible )
+    set point to dual of halfspace relative to feasible point
+    halfspace is normal coefficients and offset.
+
+  returns:
+    false if feasible point is outside of hull (error message already reported)
+    overwrites coordinates for point at dim coords
+    nextp= next point (coords)
+
+  design:
+    compute distance from feasible point to halfspace
+    divide each normal coefficient by -dist
+*/
+boolT qh_sethalfspace (int dim, coordT *coords, coordT **nextp, 
+         coordT *normal, coordT *offset, coordT *feasible) {
+  coordT *normp= normal, *feasiblep= feasible, *coordp= coords;
+  realT dist;
+  realT r; /*bug fix*/
+  int k;
+  boolT zerodiv;
+
+  dist= *offset;
+  for (k= dim; k--; )
+    dist += *(normp++) * *(feasiblep++);
+  if (dist > 0)
+    goto LABELerroroutside;
+  normp= normal;
+  if (dist < -qh MINdenom) {
+    for (k= dim; k--; )
+      *(coordp++)= *(normp++) / -dist;
+  }else {
+    for (k= dim; k--; ) {
+      *(coordp++)= qh_divzero (*(normp++), -dist, qh MINdenom_1, &zerodiv);
+      if (zerodiv) 
+        goto LABELerroroutside;
+    }
+  }
+  *nextp= coordp;
+  if (qh IStracing >= 4) {
+    fprintf (qh ferr, "qh_sethalfspace: halfspace at offset %6.2g to point: ", *offset);
+    for (k= dim, coordp= coords; k--; ) {
+      r= *coordp++;
+      fprintf (qh ferr, " %6.2g", r);
+    }
+    fprintf (qh ferr, "\n");
+  }
+  return True;
+LABELerroroutside:
+  feasiblep= feasible;
+  normp= normal;
+  fprintf(qh ferr, "qhull input error: feasible point is not clearly inside halfspace\nfeasible point: ");
+  for (k= dim; k--; )
+    fprintf (qh ferr, qh_REAL_1, r=*(feasiblep++));
+  fprintf (qh ferr, "\n     halfspace: "); 
+  for (k= dim; k--; )
+    fprintf (qh ferr, qh_REAL_1, r=*(normp++));
+  fprintf (qh ferr, "\n     at offset: ");
+  fprintf (qh ferr, qh_REAL_1, *offset);
+  fprintf (qh ferr, " and distance: ");
+  fprintf (qh ferr, qh_REAL_1, dist);
+  fprintf (qh ferr, "\n");
+  return False;
+} /* sethalfspace */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sethalfspace_all">-</a>
+  
+  qh_sethalfspace_all( dim, count, halfspaces, feasible )
+    generate dual for halfspace intersection with feasible point
+    array of count halfspaces
+      each halfspace is normal coefficients followed by offset 
+      the origin is inside the halfspace if the offset is negative
+
+  returns:
+    malloc'd array of count X dim-1 points
+
+  notes:
+    call before qh_init_B or qh_initqhull_globals 
+    unused/untested code: please email bradb@shore.net if this works ok for you
+    If using option 'Fp', also set qh feasible_point. It is a malloc'd array 
+      that is freed by qh_freebuffers.
+
+  design:
+    see qh_sethalfspace
+*/
+coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible) {
+  int i, newdim;
+  pointT *newpoints;
+  coordT *coordp, *normalp, *offsetp;
+
+  trace0((qh ferr, "qh_sethalfspace_all: compute dual for halfspace intersection\n"));
+  newdim= dim - 1;
+  if (!(newpoints=(coordT*)malloc(count*newdim*sizeof(coordT)))){
+    fprintf(qh ferr, "qhull error: insufficient memory to compute dual of %d halfspaces\n",
+          count);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  coordp= newpoints;
+  normalp= halfspaces;
+  for (i= 0; i < count; i++) {
+    offsetp= normalp + newdim;
+    if (!qh_sethalfspace (newdim, coordp, &coordp, normalp, offsetp, feasible)) {
+      fprintf (qh ferr, "The halfspace was at index %d\n", i);
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+    normalp= offsetp + 1;
+  }
+  return newpoints;
+} /* sethalfspace_all */
+
+  
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sharpnewfacets">-</a>
+  
+  qh_sharpnewfacets()
+
+  returns:
+    true if could be an acute angle (facets in different quadrants)
+  notes:
+    for qh_findbest
+
+  design:
+    for all facets on qh.newfacet_list
+      if two facets are in different quadrants
+        set issharp
+*/
+boolT qh_sharpnewfacets () {
+  facetT *facet;
+  boolT issharp = False;
+  int *quadrant, k;
+  
+  quadrant= (int*)qh_memalloc (qh hull_dim * sizeof(int));
+  FORALLfacet_(qh newfacet_list) {
+    if (facet == qh newfacet_list) {
+      for (k= qh hull_dim; k--; )
+       quadrant[ k]= (facet->normal[ k] > 0);
+    }else {
+      for (k= qh hull_dim; k--; ) {
+        if (quadrant[ k] != (facet->normal[ k] > 0)) {
+          issharp= True;
+          break;
+        }
+      }
+    }
+    if (issharp)
+      break;
+  }
+  qh_memfree( quadrant, qh hull_dim * sizeof(int));
+  trace3((qh ferr, "qh_sharpnewfacets: %d\n", issharp));
+  return issharp;
+} /* sharpnewfacets */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="voronoi_center">-</a>
+  
+  qh_voronoi_center( dim, points )
+    return Voronoi center for a set of points
+    dim is the orginal dimension of the points
+    gh.gm_matrix/qh.gm_row are scratch buffers
+
+  returns:
+    center as a temporary point
+    if non-simplicial, 
+      returns center for max simplex of points
+
+  notes:
+    from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65
+
+  design:
+    if non-simplicial
+      determine max simplex for points
+    translate point0 of simplex to origin
+    compute sum of squares of diagonal
+    compute determinate
+    compute Voronoi center (see Bowyer & Woodwark)
+*/
+pointT *qh_voronoi_center (int dim, setT *points) {
+  pointT *point, **pointp, *point0;
+  pointT *center= (pointT*)qh_memalloc (qh center_size);
+  setT *simplex;
+  int i, j, k, size= qh_setsize(points);
+  coordT *gmcoord;
+  realT *diffp, sum2, *sum2row, *sum2p, det, factor;
+  boolT nearzero, infinite;
+
+  if (size == dim+1)
+    simplex= points;
+  else if (size < dim+1) {
+    fprintf (qh ferr, "qhull internal error (qh_voronoi_center):\n  need at least %d points to construct a Voronoi center\n",
+            dim+1);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }else {
+    simplex= qh_settemp (dim+1);
+    qh_maxsimplex (dim, points, NULL, 0, &simplex);
+  }
+  point0= SETfirstt_(simplex, pointT);
+  gmcoord= qh gm_matrix;
+  for (k=0; k < dim; k++) {
+    qh gm_row[k]= gmcoord;
+    FOREACHpoint_(simplex) {
+      if (point != point0)
+        *(gmcoord++)= point[k] - point0[k];
+    }
+  }
+  sum2row= gmcoord;
+  for (i=0; i < dim; i++) {
+    sum2= 0.0;
+    for (k= 0; k < dim; k++) {
+      diffp= qh gm_row[k] + i;
+      sum2 += *diffp * *diffp;
+    }
+    *(gmcoord++)= sum2;
+  }
+  det= qh_determinant (qh gm_row, dim, &nearzero);
+  factor= qh_divzero (0.5, det, qh MINdenom, &infinite);
+  if (infinite) {
+    for (k=dim; k--; )
+      center[k]= qh_INFINITE;
+    if (qh IStracing)
+      qh_printpoints (qh ferr, "qh_voronoi_center: at infinity for ", simplex);
+  }else {
+    for (i=0; i < dim; i++) {
+      gmcoord= qh gm_matrix;
+      sum2p= sum2row;
+      for (k=0; k < dim; k++) {
+       qh gm_row[k]= gmcoord;
+       if (k == i) {
+         for (j= dim; j--; )
+           *(gmcoord++)= *sum2p++;
+       }else {
+         FOREACHpoint_(simplex) {
+           if (point != point0)
+             *(gmcoord++)= point[k] - point0[k];
+         }
+       }
+      }
+      center[i]= qh_determinant (qh gm_row, dim, &nearzero)*factor + point0[i];
+    }
+#ifndef qh_NOtrace
+    if (qh IStracing >= 3) {
+      fprintf (qh ferr, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
+      qh_printmatrix (qh ferr, "center:", &center, 1, dim);
+      if (qh IStracing >= 5) {
+       qh_printpoints (qh ferr, "points", simplex);
+       FOREACHpoint_(simplex)
+         fprintf (qh ferr, "p%d dist %.2g, ", qh_pointid (point),
+                  qh_pointdist (point, center, dim));
+       fprintf (qh ferr, "\n");
+      }
+    }
+#endif
+  }
+  if (simplex != points)
+    qh_settempfree (&simplex);
+  return center;
+} /* voronoi_center */
+
diff --git a/extern/qhull/src/global.c b/extern/qhull/src/global.c
new file mode 100755 (executable)
index 0000000..d3e141a
--- /dev/null
@@ -0,0 +1,2018 @@
+/*<html><pre>  -<a                             href="qh-globa.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   global.c
+   initializes all the globals of the qhull application
+
+   see README
+
+   see qhull.h for qh.globals and function prototypes
+
+   see qhull_a.h for internal functions
+
+   copyright (c) 1993-2002, The Geometry Center
+ */
+
+#include "qhull_a.h"
+
+/*========= qh definition =======================*/
+
+#if qh_QHpointer
+qhT *qh_qh= NULL;      /* pointer to all global variables */
+#else
+qhT qh_qh;                     /* all global variables.
+                          Add "= {0}" if this causes a compiler error.
+                          Also qh_qhstat in stat.c and qhmem in mem.c.  */
+#endif
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="appendprint">-</a>
+
+  qh_appendprint( printFormat )
+    append printFormat to qh.PRINTout unless already defined
+*/
+void qh_appendprint (qh_PRINT format) {
+  int i;
+
+  for (i=0; i < qh_PRINTEND; i++) {
+    if (qh PRINTout[i] == format && format != qh_PRINTqhull)
+      break;
+    if (!qh PRINTout[i]) {
+      qh PRINTout[i]= format;
+      break;
+    }
+  }
+} /* appendprint */
+     
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="checkflags">-</a>
+  
+  qh_checkflags( commandStr, hiddenFlags )
+    errors if commandStr contains hiddenFlags
+    hiddenFlags starts and ends with a space and is space deliminated (checked)
+
+  notes:
+    ignores first word (e.g., "qconvex i")
+    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
+  
+  see:
+    qh_initflags() initializes Qhull according to commandStr
+*/
+void qh_checkflags(char *command, char *hiddenflags) {
+  char *s= command, *t, *chkerr, key, opt, prevopt;
+  char chkkey[]= "   ";
+  char chkopt[]=  "    ";
+  char chkopt2[]= "     ";
+
+  if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
+    fprintf(qh ferr, "qhull error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"", hiddenflags);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (strpbrk(hiddenflags, ",\n\r\t")) { 
+    fprintf(qh ferr, "qhull error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"", hiddenflags);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  while (*s && !isspace(*s))  /* skip program name */
+    s++;
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    key = *s++;
+    chkerr = NULL;
+    if (key == '\'') {         /* TO 'file name' */
+      t= strchr(s, '\'');
+      if (!t) {
+       fprintf(qh ferr, "qhull error (qh_checkflags): missing the 2nd single-quote for:\n%s\n", s-1);
+       qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+      s= t+1;
+      continue;
+    }
+    chkkey[1]= key;
+    if (strstr(hiddenflags, chkkey)) {
+      chkerr= chkkey;
+    }else if (isupper(key)) {
+      opt= ' ';
+      prevopt= ' ';
+      chkopt[1]= key;
+      chkopt2[1]= key;
+      while (!chkerr && *s && !isspace(*s)) {
+       opt= *s++;
+       if (isalpha(opt)) {
+         chkopt[2]= opt;
+         if (strstr(hiddenflags, chkopt))
+           chkerr= chkopt;
+         if (prevopt != ' ') {
+           chkopt2[2]= prevopt;
+           chkopt2[3]= opt;
+           if (strstr(hiddenflags, chkopt2))
+             chkerr= chkopt2;
+         }
+       }else if (key == 'Q' && isdigit(opt) && prevopt != 'b' 
+             && (prevopt == ' ' || islower(prevopt))) {
+           chkopt[2]= opt;
+           if (strstr(hiddenflags, chkopt))
+             chkerr= chkopt;
+       }else {
+         qh_strtod (s-1, &t);
+         if (s < t)
+           s= t;
+       }
+        prevopt= opt;
+      }
+    }
+    if (chkerr) {
+      *chkerr= '\'';
+      chkerr[strlen(chkerr)-1]=  '\'';
+      fprintf(qh ferr, "qhull error: option %s is not used with this program.\n             It may be used with qhull.\n", chkerr);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+  }
+} /* checkflags */
+    
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="clock">-</a>
+  
+  qh_clock()
+    return user CPU time in 100ths (qh_SECtick)
+    only defined for qh_CLOCKtype == 2
+
+  notes:
+    use first value to determine time 0
+    from Stevens '92 8.15
+*/
+unsigned long qh_clock (void) {
+
+#if (qh_CLOCKtype == 2)
+  struct tms time;
+  static long clktck;  /* initialized first call */
+  double ratio, cpu;
+  unsigned long ticks;
+
+  if (!clktck) {
+    if ((clktck= sysconf (_SC_CLK_TCK)) < 0) {
+      fprintf (qh ferr, "qhull internal error (qh_clock): sysconf() failed.  Use qh_CLOCKtype 1 in user.h\n");
+      qh_errexit (qh_ERRqhull, NULL, NULL);
+    }
+  }
+  if (times (&time) == -1) {
+    fprintf (qh ferr, "qhull internal error (qh_clock): times() failed.  Use qh_CLOCKtype 1 in user.h\n");
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  ratio= qh_SECticks / (double)clktck;
+  ticks= time.tms_utime * ratio;
+  return ticks;
+#else
+  fprintf (qh ferr, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user.h\n");
+  qh_errexit (qh_ERRqhull, NULL, NULL); /* never returns */
+  return 0;
+#endif
+} /* clock */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="freebuffers">-</a>
+
+  qh_freebuffers()
+    free up global memory buffers
+
+  notes:
+    must match qh_initbuffers()
+*/
+void qh_freebuffers (void) {
+
+  trace5((qh ferr, "qh_freebuffers: freeing up global memory buffers\n"));
+  /* allocated by qh_initqhull_buffers */
+  qh_memfree (qh NEARzero, qh hull_dim * sizeof(realT));
+  qh_memfree (qh lower_threshold, (qh input_dim+1) * sizeof(realT));
+  qh_memfree (qh upper_threshold, (qh input_dim+1) * sizeof(realT));
+  qh_memfree (qh lower_bound, (qh input_dim+1) * sizeof(realT));
+  qh_memfree (qh upper_bound, (qh input_dim+1) * sizeof(realT));
+  qh_memfree (qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
+  qh_memfree (qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
+  qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
+  qh lower_bound= qh upper_bound= NULL;
+  qh gm_matrix= NULL;
+  qh gm_row= NULL;
+  qh_setfree (&qh other_points);
+  qh_setfree (&qh del_vertices);
+  qh_setfree (&qh coplanarset);
+  if (qh line)                /* allocated by qh_readinput, freed if no error */
+    free (qh line);
+  if (qh half_space)
+    free (qh half_space);
+  if (qh temp_malloc)
+    free (qh temp_malloc);
+  if (qh feasible_point)      /* allocated by qh_readfeasible */
+    free (qh feasible_point);
+  if (qh feasible_string)     /* allocated by qh_initflags */
+    free (qh feasible_string);
+  qh line= qh feasible_string= NULL;
+  qh half_space= qh feasible_point= qh temp_malloc= NULL;
+  /* usually allocated by qh_readinput */
+  if (qh first_point && qh POINTSmalloc) {
+    free(qh first_point);
+    qh first_point= NULL;
+  }
+  if (qh input_points && qh input_malloc) { /* set by qh_joggleinput */
+    free (qh input_points);
+    qh input_points= NULL;
+  }
+  trace5((qh ferr, "qh_freebuffers: finished\n"));
+} /* freebuffers */
+
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="freebuild">-</a>
+
+  qh_freebuild( allmem )
+    free global memory used by qh_initbuild and qh_buildhull
+    if !allmem,
+      does not free short memory (freed by qh_memfreeshort)
+
+  design:
+    free centrums
+    free each vertex
+    mark unattached ridges
+    for each facet
+      free ridges
+      free outside set, coplanar set, neighbor set, ridge set, vertex set
+      free facet
+    free hash table
+    free interior point
+    free merge set
+    free temporary sets
+*/
+void qh_freebuild (boolT allmem) {
+  facetT *facet;
+  vertexT *vertex;
+  ridgeT *ridge, **ridgep;
+  mergeT *merge, **mergep;
+
+  trace1((qh ferr, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
+  if (qh del_vertices)
+    qh_settruncate (qh del_vertices, 0);
+  if (allmem) {
+    qh_clearcenters (qh_ASnone);
+    while ((vertex= qh vertex_list)) {
+      if (vertex->next)
+        qh_delvertex (vertex);
+      else {
+        qh_memfree (vertex, sizeof(vertexT));
+        qh newvertex_list= qh vertex_list= NULL;
+      }
+    }
+  }else if (qh VERTEXneighbors) {
+    FORALLvertices
+      qh_setfreelong (&(vertex->neighbors));
+  }
+  qh VERTEXneighbors= False;
+  qh GOODclosest= NULL;
+  if (allmem) {
+    FORALLfacets {
+      FOREACHridge_(facet->ridges)
+        ridge->seen= False;
+    }
+    FORALLfacets {
+      if (facet->visible) {
+       FOREACHridge_(facet->ridges) {
+         if (!otherfacet_(ridge, facet)->visible)
+           ridge->seen= True;  /* an unattached ridge */
+       }
+      }
+    }
+    while ((facet= qh facet_list)) {
+      FOREACHridge_(facet->ridges) {
+        if (ridge->seen) {
+          qh_setfree(&(ridge->vertices));
+          qh_memfree(ridge, sizeof(ridgeT));
+        }else
+          ridge->seen= True;
+      }
+      qh_setfree (&(facet->outsideset));
+      qh_setfree (&(facet->coplanarset));
+      qh_setfree (&(facet->neighbors));
+      qh_setfree (&(facet->ridges));
+      qh_setfree (&(facet->vertices));
+      if (facet->next)
+        qh_delfacet (facet);
+      else {
+        qh_memfree (facet, sizeof(facetT));
+        qh visible_list= qh newfacet_list= qh facet_list= NULL;
+      }
+    }
+  }else {
+    FORALLfacets {
+      qh_setfreelong (&(facet->outsideset));
+      qh_setfreelong (&(facet->coplanarset));
+      if (!facet->simplicial) {
+        qh_setfreelong (&(facet->neighbors));
+        qh_setfreelong (&(facet->ridges));
+        qh_setfreelong (&(facet->vertices));
+      }
+    }
+  }
+  qh_setfree (&(qh hash_table));
+  qh_memfree (qh interior_point, qh normal_size);
+  qh interior_point= NULL;
+  FOREACHmerge_(qh facet_mergeset)  /* usually empty */
+    qh_memfree (merge, sizeof(mergeT));
+  qh facet_mergeset= NULL;  /* temp set */
+  qh degen_mergeset= NULL;  /* temp set */
+  qh_settempfree_all();
+} /* freebuild */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="freeqhull">-</a>
+
+  qh_freeqhull( allmem )
+    free global memory
+    if !allmem,
+      does not free short memory (freed by qh_memfreeshort)
+
+  notes:
+    sets qh.NOerrexit in case caller forgets to
+
+  design:
+    free global and temporary memory from qh_initbuild and qh_buildhull
+    free buffers
+    free statistics
+*/
+void qh_freeqhull (boolT allmem) {
+
+  trace1((qh ferr, "qh_freeqhull: free global memory\n"));
+  qh NOerrexit= True;  /* no more setjmp since called at exit */
+  qh_freebuild (allmem);
+  qh_freebuffers();
+  qh_freestatistics();
+#if qh_QHpointer
+  free (qh_qh);
+  qh_qh= NULL;
+#else
+  memset((char *)&qh_qh, 0, sizeof(qhT));
+  qh NOerrexit= True;
+#endif
+} /* freeqhull */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="init_A">-</a>
+
+  qh_init_A( infile, outfile, errfile, argc, argv )
+    initialize memory and stdio files
+    convert input options to option string (qh.qhull_command)
+
+  notes:
+    infile may be NULL if qh_readpoints() is not called
+
+    errfile should always be defined.  It is used for reporting
+    errors.  outfile is used for output and format options.
+
+    argc/argv may be 0/NULL
+
+    called before error handling initialized
+    qh_errexit() may not be used
+*/
+void qh_init_A (FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
+  qh_meminit (errfile);
+  qh_initqhull_start (infile, outfile, errfile);
+  qh_init_qhull_command (argc, argv);
+} /* init_A */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="init_B">-</a>
+
+  qh_init_B( points, numpoints, dim, ismalloc )
+    initialize globals for points array
+
+    points has numpoints dim-dimensional points
+      points[0] is the first coordinate of the first point
+      points[1] is the second coordinate of the first point
+      points[dim] is the first coordinate of the second point
+
+    ismalloc=True
+      Qhull will call free(points) on exit or input transformation
+    ismalloc=False
+      Qhull will allocate a new point array if needed for input transformation
+
+    qh.qhull_command
+      is the option string.
+      It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
+
+  returns:
+    if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
+      projects the input to a new point array
+
+        if qh.DELAUNAY,
+          qh.hull_dim is increased by one
+        if qh.ATinfinity,
+          qh_projectinput adds point-at-infinity for Delaunay tri.
+
+    if qh.SCALEinput
+      changes the upper and lower bounds of the input, see qh_scaleinput()
+
+    if qh.ROTATEinput
+      rotates the input by a random rotation, see qh_rotateinput()
+      if qh.DELAUNAY
+        rotates about the last coordinate
+
+  notes:
+    called after points are defined
+    qh_errexit() may be used
+*/
+void qh_init_B (coordT *points, int numpoints, int dim, boolT ismalloc) {
+  qh_initqhull_globals (points, numpoints, dim, ismalloc);
+  if (qhmem.LASTsize == 0)
+    qh_initqhull_mem();
+  /* mem.c and qset.c are initialized */
+  qh_initqhull_buffers();
+  qh_initthresholds (qh qhull_command);
+  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay))
+    qh_projectinput();
+  if (qh SCALEinput)
+    qh_scaleinput();
+  if (qh ROTATErandom >= 0) {
+    qh_randommatrix (qh gm_matrix, qh hull_dim, qh gm_row);
+    if (qh DELAUNAY) {
+      int k, lastk= qh hull_dim-1;
+      for (k= 0; k < lastk; k++) {
+        qh gm_row[k][lastk]= 0.0;
+        qh gm_row[lastk][k]= 0.0;
+      }
+      qh gm_row[lastk][lastk]= 1.0;
+    }
+    qh_gram_schmidt (qh hull_dim, qh gm_row);
+    qh_rotateinput (qh gm_row);
+  }
+} /* init_B */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="init_qhull_command">-</a>
+
+  qh_init_qhull_command( argc, argv )
+    build qh.qhull_command from argc/argv
+
+  returns:
+    a space-deliminated string of options (just as typed)
+
+  notes:
+    makes option string easy to input and output
+
+    argc/argv may be 0/NULL
+*/
+void qh_init_qhull_command(int argc, char *argv[]) {
+  int i;
+  char *s;
+
+  if (argc) {
+    if ((s= strrchr( argv[0], '\\'))) /* Borland gives full path */
+      strcpy (qh qhull_command, s+1);
+    else
+      strcpy (qh qhull_command, argv[0]);
+    if ((s= strstr (qh qhull_command, ".EXE"))
+    ||  (s= strstr (qh qhull_command, ".exe")))
+      *s= '\0';
+  }
+  for (i=1; i < argc; i++) {
+    if (strlen (qh qhull_command) + strlen(argv[i]) + 1 < sizeof(qh qhull_command)) {
+      strcat (qh qhull_command, " ");
+      strcat (qh qhull_command, argv[i]);
+    }else {
+      fprintf (qh ferr, "qhull input error: more than %d characters in command line\n",
+        (int)sizeof(qh qhull_command));
+      exit (1);  /* can not use qh_errexit */
+    }
+  }
+} /* init_qhull_command */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initflags">-</a>
+
+  qh_initflags( commandStr )
+    set flags and initialized constants from commandStr
+
+  returns:
+    sets qh.qhull_command to command if needed
+
+  notes:
+    ignores first word (e.g., "qhull d")
+    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
+
+  see:
+    qh_initthresholds() continues processing of 'Pdn' and 'PDn'
+    'prompt' in unix.c for documentation
+
+  design:
+    for each space-deliminated option group
+      if top-level option
+        check syntax
+        append approriate option to option string
+        set appropriate global variable or append printFormat to print options
+      else
+        for each sub-option
+          check syntax
+          append approriate option to option string
+          set appropriate global variable or append printFormat to print options
+
+
+*/
+void qh_initflags(char *command) {
+  int k, i, lastproject;
+  char *s= command, *t, *prev_s, *start, key;
+  boolT isgeom= False, wasproject;
+  realT r;
+
+  if (command != &qh qhull_command[0]) {
+    *qh qhull_command= '\0';
+    strncat( qh qhull_command, command, sizeof( qh qhull_command));
+  }
+  while (*s && !isspace(*s))  /* skip program name */
+    s++;
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    prev_s= s;
+    switch (*s++) {
+    case 'd':
+      qh_option ("delaunay", NULL, NULL);
+      qh DELAUNAY= True;
+      break;
+    case 'f':
+      qh_option ("facets", NULL, NULL);
+      qh_appendprint (qh_PRINTfacets);
+      break;
+    case 'i':
+      qh_option ("incidence", NULL, NULL);
+      qh_appendprint (qh_PRINTincidences);
+      break;
+    case 'm':
+      qh_option ("mathematica", NULL, NULL);
+      qh_appendprint (qh_PRINTmathematica);
+      break;
+    case 'n':
+      qh_option ("normals", NULL, NULL);
+      qh_appendprint (qh_PRINTnormals);
+      break;
+    case 'o':
+      qh_option ("offFile", NULL, NULL);
+      qh_appendprint (qh_PRINToff);
+      break;
+    case 'p':
+      qh_option ("points", NULL, NULL);
+      qh_appendprint (qh_PRINTpoints);
+      break;
+    case 's':
+      qh_option ("summary", NULL, NULL);
+      qh PRINTsummary= True;
+      break;
+    case 'v':
+      qh_option ("voronoi", NULL, NULL);
+      qh VORONOI= True;
+      qh DELAUNAY= True;
+      break;
+    case 'A':
+      if (!isdigit(*s) && *s != '.' && *s != '-')
+       fprintf(qh ferr, "qhull warning: no maximum cosine angle given for option 'An'.  Ignored.\n");
+      else {
+       if (*s == '-') {
+         qh premerge_cos= -qh_strtod (s, &s);
+          qh_option ("Angle-premerge-", NULL, &qh premerge_cos);
+         qh PREmerge= True;
+       }else {
+         qh postmerge_cos= qh_strtod (s, &s);
+          qh_option ("Angle-postmerge", NULL, &qh postmerge_cos);
+         qh POSTmerge= True;
+       }
+       qh MERGING= True;
+      }
+      break;
+    case 'C':
+      if (!isdigit(*s) && *s != '.' && *s != '-')
+       fprintf(qh ferr, "qhull warning: no centrum radius given for option 'Cn'.  Ignored.\n");
+      else {
+       if (*s == '-') {
+         qh premerge_centrum= -qh_strtod (s, &s);
+          qh_option ("Centrum-premerge-", NULL, &qh premerge_centrum);
+         qh PREmerge= True;
+       }else {
+         qh postmerge_centrum= qh_strtod (s, &s);
+          qh_option ("Centrum-postmerge", NULL, &qh postmerge_centrum);
+         qh POSTmerge= True;
+       }
+       qh MERGING= True;
+      }
+      break;
+    case 'E':
+      if (*s == '-')
+       fprintf(qh ferr, "qhull warning: negative maximum roundoff given for option 'An'.  Ignored.\n");
+      else if (!isdigit(*s))
+       fprintf(qh ferr, "qhull warning: no maximum roundoff given for option 'En'.  Ignored.\n");
+      else {
+       qh DISTround= qh_strtod (s, &s);
+        qh_option ("Distance-roundoff", NULL, &qh DISTround);
+       qh SETroundoff= True;
+      }
+      break;
+    case 'H':
+      start= s;
+      qh HALFspace= True;
+      qh_strtod (s, &t);
+      while (t > s)  {
+        if (*t && !isspace (*t)) {
+         if (*t == ',')
+           t++;
+         else
+           fprintf (qh ferr, "qhull warning: origin for Halfspace intersection should be 'Hn,n,n,...'\n");
+       }
+        s= t;
+       qh_strtod (s, &t);
+      }
+      if (start < t) {
+        if (!(qh feasible_string= (char*)calloc (t-start+1, 1))) {
+          fprintf(qh ferr, "qhull error: insufficient memory for 'Hn,n,n'\n");
+          qh_errexit(qh_ERRmem, NULL, NULL);
+        }
+        strncpy (qh feasible_string, start, t-start);
+        qh_option ("Halfspace-about", NULL, NULL);
+        qh_option (qh feasible_string, NULL, NULL);
+      }else
+        qh_option ("Halfspace", NULL, NULL);
+      break;
+    case 'R':
+      if (!isdigit(*s))
+       fprintf(qh ferr, "qhull warning: missing random perturbation for option 'Rn'.  Ignored\n");
+      else {
+       qh RANDOMfactor= qh_strtod (s, &s);
+        qh_option ("Random_perturb", NULL, &qh RANDOMfactor);
+        qh RANDOMdist= True;
+      }
+      break;
+    case 'V':
+      if (!isdigit(*s) && *s != '-')
+       fprintf(qh ferr, "qhull warning: missing visible distance for option 'Vn'.  Ignored\n");
+      else {
+       qh MINvisible= qh_strtod (s, &s);
+        qh_option ("Visible", NULL, &qh MINvisible);
+      }
+      break;
+    case 'U':
+      if (!isdigit(*s) && *s != '-')
+       fprintf(qh ferr, "qhull warning: missing coplanar distance for option 'Un'.  Ignored\n");
+      else {
+       qh MAXcoplanar= qh_strtod (s, &s);
+        qh_option ("U-coplanar", NULL, &qh MAXcoplanar);
+      }
+      break;
+    case 'W':
+      if (*s == '-')
+       fprintf(qh ferr, "qhull warning: negative outside width for option 'Wn'.  Ignored.\n");
+      else if (!isdigit(*s))
+       fprintf(qh ferr, "qhull warning: missing outside width for option 'Wn'.  Ignored\n");
+      else {
+       qh MINoutside= qh_strtod (s, &s);
+        qh_option ("W-outside", NULL, &qh MINoutside);
+        qh APPROXhull= True;
+      }
+      break;
+    /************  sub menus ***************/
+    case 'F':
+      while (*s && !isspace(*s)) {
+       switch(*s++) {
+       case 'a':
+         qh_option ("Farea", NULL, NULL);
+         qh_appendprint (qh_PRINTarea);
+         qh GETarea= True;
+         break;
+       case 'A':
+         qh_option ("FArea-total", NULL, NULL);
+         qh GETarea= True;
+         break;
+        case 'c':
+          qh_option ("Fcoplanars", NULL, NULL);
+          qh_appendprint (qh_PRINTcoplanars);
+          break;
+        case 'C':
+          qh_option ("FCentrums", NULL, NULL);
+          qh_appendprint (qh_PRINTcentrums);
+          break;
+       case 'd':
+          qh_option ("Fd-cdd-in", NULL, NULL);
+         qh CDDinput= True;
+         break;
+       case 'D':
+          qh_option ("FD-cdd-out", NULL, NULL);
+         qh CDDoutput= True;
+         break;
+       case 'F':
+         qh_option ("FFacets-xridge", NULL, NULL);
+          qh_appendprint (qh_PRINTfacets_xridge);
+         break;
+        case 'i':
+          qh_option ("Finner", NULL, NULL);
+          qh_appendprint (qh_PRINTinner);
+          break;
+        case 'I':
+          qh_option ("FIDs", NULL, NULL);
+          qh_appendprint (qh_PRINTids);
+          break;
+        case 'm':
+          qh_option ("Fmerges", NULL, NULL);
+          qh_appendprint (qh_PRINTmerges);
+          break;
+        case 'n':
+          qh_option ("Fneighbors", NULL, NULL);
+          qh_appendprint (qh_PRINTneighbors);
+          break;
+        case 'N':
+          qh_option ("FNeighbors-vertex", NULL, NULL);
+          qh_appendprint (qh_PRINTvneighbors);
+          break;
+        case 'o':
+          qh_option ("Fouter", NULL, NULL);
+          qh_appendprint (qh_PRINTouter);
+          break;
+       case 'O':
+         if (qh PRINToptions1st) {
+           qh_option ("FOptions", NULL, NULL);
+           qh_appendprint (qh_PRINToptions);
+         }else
+           qh PRINToptions1st= True;
+         break;
+       case 'p':
+         qh_option ("Fpoint-intersect", NULL, NULL);
+         qh_appendprint (qh_PRINTpointintersect);
+         break;
+       case 'P':
+         qh_option ("FPoint-nearest", NULL, NULL);
+         qh_appendprint (qh_PRINTpointnearest);
+         break;
+       case 'Q':
+         qh_option ("FQhull", NULL, NULL);
+         qh_appendprint (qh_PRINTqhull);
+         break;
+        case 's':
+          qh_option ("Fsummary", NULL, NULL);
+          qh_appendprint (qh_PRINTsummary);
+          break;
+        case 'S':
+          qh_option ("FSize", NULL, NULL);
+          qh_appendprint (qh_PRINTsize);
+          qh GETarea= True;
+          break;
+        case 't':
+          qh_option ("Ftriangles", NULL, NULL);
+          qh_appendprint (qh_PRINTtriangles);
+          break;
+        case 'v':
+          /* option set in qh_initqhull_globals */
+          qh_appendprint (qh_PRINTvertices);
+          break;
+        case 'V':
+          qh_option ("FVertex-average", NULL, NULL);
+          qh_appendprint (qh_PRINTaverage);
+          break;
+       case 'x':
+         qh_option ("Fxtremes", NULL, NULL);
+         qh_appendprint (qh_PRINTextremes);
+         break;
+       default:
+         s--;
+         fprintf (qh ferr, "qhull warning: unknown 'F' output option %c, rest ignored\n", (int)s[0]);
+         while (*++s && !isspace(*s));
+         break;
+       }
+      }
+      break;
+    case 'G':
+      isgeom= True;
+      qh_appendprint (qh_PRINTgeom);
+      while (*s && !isspace(*s)) {
+       switch(*s++) {
+        case 'a':
+          qh_option ("Gall-points", NULL, NULL);
+          qh PRINTdots= True;
+          break;
+        case 'c':
+          qh_option ("Gcentrums", NULL, NULL);
+          qh PRINTcentrums= True;
+          break;
+       case 'h':
+          qh_option ("Gintersections", NULL, NULL);
+         qh DOintersections= True;
+         break;
+       case 'i':
+          qh_option ("Ginner", NULL, NULL);
+         qh PRINTinner= True;
+         break;
+       case 'n':
+          qh_option ("Gno-planes", NULL, NULL);
+         qh PRINTnoplanes= True;
+         break;
+       case 'o':
+          qh_option ("Gouter", NULL, NULL);
+         qh PRINTouter= True;
+         break;
+       case 'p':
+          qh_option ("Gpoints", NULL, NULL);
+         qh PRINTcoplanar= True;
+         break;
+       case 'r':
+          qh_option ("Gridges", NULL, NULL);
+         qh PRINTridges= True;
+         break;
+       case 't':
+          qh_option ("Gtransparent", NULL, NULL);
+         qh PRINTtransparent= True;
+         break;
+       case 'v':
+          qh_option ("Gvertices", NULL, NULL);
+         qh PRINTspheres= True;
+         break;
+       case 'D':
+         if (!isdigit (*s))
+           fprintf (qh ferr, "qhull input error: missing dimension for option 'GDn'\n");
+         else {
+           if (qh DROPdim >= 0)
+             fprintf (qh ferr, "qhull warning: can only drop one dimension.  Previous 'GD%d' ignored\n",
+                  qh DROPdim);
+           qh DROPdim= qh_strtol (s, &s);
+            qh_option ("GDrop-dim", &qh DROPdim, NULL);
+          }
+         break;
+       default:
+         s--;
+         fprintf (qh ferr, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
+         while (*++s && !isspace(*s));
+         break;
+       }
+      }
+      break;
+    case 'P':
+      while (*s && !isspace(*s)) {
+       switch(*s++) {
+       case 'd': case 'D':  /* see qh_initthresholds() */
+         key= s[-1];
+         i= qh_strtol (s, &s);
+         r= 0;
+         if (*s == ':') {
+           s++;
+           r= qh_strtod (s, &s);
+         }
+         if (key == 'd')
+           qh_option ("Pdrop-facets-dim-less", &i, &r);
+         else
+           qh_option ("PDrop-facets-dim-more", &i, &r);
+         break;
+        case 'g':
+          qh_option ("Pgood-facets", NULL, NULL);
+          qh PRINTgood= True;
+          break;
+        case 'G':
+          qh_option ("PGood-facet-neighbors", NULL, NULL);
+          qh PRINTneighbors= True;
+          break;
+        case 'o':
+          qh_option ("Poutput-forced", NULL, NULL);
+          qh FORCEoutput= True;
+          break;
+        case 'p':
+          qh_option ("Pprecision-ignore", NULL, NULL);
+          qh PRINTprecision= False;
+          break;
+       case 'A':
+         if (!isdigit (*s))
+           fprintf (qh ferr, "qhull input error: missing facet count for keep area option 'PAn'\n");
+         else {
+           qh KEEParea= qh_strtol (s, &s);
+            qh_option ("PArea-keep", &qh KEEParea, NULL);
+            qh GETarea= True;
+          }
+         break;
+       case 'F':
+         if (!isdigit (*s))
+           fprintf (qh ferr, "qhull input error: missing facet area for option 'PFn'\n");
+         else {
+           qh KEEPminArea= qh_strtod (s, &s);
+            qh_option ("PFacet-area-keep", NULL, &qh KEEPminArea);
+            qh GETarea= True;
+          }
+         break;
+       case 'M':
+         if (!isdigit (*s))
+           fprintf (qh ferr, "qhull input error: missing merge count for option 'PMn'\n");
+         else {
+           qh KEEPmerge= qh_strtol (s, &s);
+            qh_option ("PMerge-keep", &qh KEEPmerge, NULL);
+          }
+         break;
+       default:
+         s--;
+         fprintf (qh ferr, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[0]);
+         while (*++s && !isspace(*s));
+         break;
+       }
+      }
+      break;
+    case 'Q':
+      lastproject= -1;
+      while (*s && !isspace(*s)) {
+       switch(*s++) {
+       case 'b': case 'B':  /* handled by qh_initthresholds */
+         key= s[-1];
+         if (key == 'b' && *s == 'B') {
+           s++;
+           r= qh_DEFAULTbox;
+           qh SCALEinput= True;
+           qh_option ("QbBound-unit-box", NULL, &r);
+           break;
+         }
+         if (key == 'b' && *s == 'b') {
+           s++;
+           qh SCALElast= True;
+           qh_option ("Qbbound-last", NULL, NULL);
+           break;
+         }
+         k= qh_strtol (s, &s);
+         r= 0.0;
+         wasproject= False;
+         if (*s == ':') {
+           s++;
+           if ((r= qh_strtod(s, &s)) == 0.0) {
+             t= s;            /* need true dimension for memory allocation */
+             while (*t && !isspace(*t)) {
+               if (toupper(*t++) == 'B'
+                && k == qh_strtol (t, &t)
+                && *t++ == ':'
+                && qh_strtod(t, &t) == 0.0) {
+                 qh PROJECTinput++;
+                 trace2((qh ferr, "qh_initflags: project dimension %d\n", k));
+                 qh_option ("Qb-project-dim", &k, NULL);
+                 wasproject= True;
+                 lastproject= k;
+                 break;
+               }
+             }
+           }
+         }
+         if (!wasproject) {
+           if (lastproject == k && r == 0.0)
+             lastproject= -1;  /* doesn't catch all possible sequences */
+           else if (key == 'b') {
+             qh SCALEinput= True;
+             if (r == 0.0)
+               r= -qh_DEFAULTbox;
+             qh_option ("Qbound-dim-low", &k, &r);
+           }else {
+             qh SCALEinput= True;
+             if (r == 0.0)
+               r= qh_DEFAULTbox;
+             qh_option ("QBound-dim-high", &k, &r);
+           }
+         }
+         break;
+       case 'c':
+         qh_option ("Qcoplanar-keep", NULL, NULL);
+         qh KEEPcoplanar= True;
+         break;
+       case 'f':
+         qh_option ("Qfurthest-outside", NULL, NULL);
+         qh BESToutside= True;
+         break;
+       case 'g':
+         qh_option ("Qgood-facets-only", NULL, NULL);
+         qh ONLYgood= True;
+         break;
+       case 'i':
+         qh_option ("Qinterior-keep", NULL, NULL);
+         qh KEEPinside= True;
+         break;
+       case 'm':
+         qh_option ("Qmax-outside-only", NULL, NULL);
+         qh ONLYmax= True;
+         break;
+       case 'r':
+         qh_option ("Qrandom-outside", NULL, NULL);
+         qh RANDOMoutside= True;
+         break;
+       case 's':
+         qh_option ("Qsearch-initial-simplex", NULL, NULL);
+         qh ALLpoints= True;
+         break;
+       case 't':
+         qh_option ("Qtriangulate", NULL, NULL);
+         qh TRIangulate= True;
+         break;
+       case 'T':
+         qh_option ("QTestPoints", NULL, NULL);
+         if (!isdigit (*s))
+           fprintf (qh ferr, "qhull input error: missing number of test points for option 'QTn'\n");
+         else {
+           qh TESTpoints= qh_strtol (s, &s);
+            qh_option ("QTestPoints", &qh TESTpoints, NULL);
+          }
+         break;
+       case 'u':
+         qh_option ("QupperDelaunay", NULL, NULL);
+         qh UPPERdelaunay= True;
+         break;
+       case 'v':
+         qh_option ("Qvertex-neighbors-convex", NULL, NULL);
+         qh TESTvneighbors= True;
+         break;
+       case 'x':
+         qh_option ("Qxact-merge", NULL, NULL);
+         qh MERGEexact= True;
+         break;
+       case 'z':
+         qh_option ("Qz-infinity-point", NULL, NULL);
+         qh ATinfinity= True;
+         break;
+       case '0':
+         qh_option ("Q0-no-premerge", NULL, NULL);
+         qh NOpremerge= True;
+         break;
+       case '1':
+         if (!isdigit(*s)) {
+           qh_option ("Q1-no-angle-sort", NULL, NULL);
+           qh ANGLEmerge= False;
+           break; 
+         }
+         switch(*s++) {
+         case '0':
+           qh_option ("Q10-no-narrow", NULL, NULL);
+           qh NOnarrow= True;
+           break; 
+         case '1':
+           qh_option ("Q11-trinormals Qtriangulate", NULL, NULL);
+           qh TRInormals= True;
+           qh TRIangulate= True;
+           break; 
+         default:
+           s--;
+           fprintf (qh ferr, "qhull warning: unknown 'Q' qhull option 1%c, rest ignored\n", (int)s[0]);
+           while (*++s && !isspace(*s));
+           break;
+         }
+         break;
+       case '2':
+         qh_option ("Q2-no-merge-independent", NULL, NULL);
+         qh MERGEindependent= False;
+         goto LABELcheckdigit;
+         break; /* no warnings */
+       case '3':
+         qh_option ("Q3-no-merge-vertices", NULL, NULL);
+         qh MERGEvertices= False;
+       LABELcheckdigit:
+         if (isdigit(*s))
+           fprintf (qh ferr, "qhull warning: can not follow '1', '2', or '3' with a digit.  '%c' skipped.\n",
+                    *s++);
+         break;
+       case '4':
+         qh_option ("Q4-avoid-old-into-new", NULL, NULL);
+         qh AVOIDold= True;
+         break;
+       case '5':
+         qh_option ("Q5-no-check-outer", NULL, NULL);
+         qh SKIPcheckmax= True;
+         break;
+       case '6':
+         qh_option ("Q6-no-concave-merge", NULL, NULL);
+         qh SKIPconvex= True;
+         break;
+       case '7':
+         qh_option ("Q7-no-breadth-first", NULL, NULL);
+         qh VIRTUALmemory= True;
+         break;
+       case '8':
+         qh_option ("Q8-no-near-inside", NULL, NULL);
+         qh NOnearinside= True;
+         break;
+       case '9':
+         qh_option ("Q9-pick-furthest", NULL, NULL);
+         qh PICKfurthest= True;
+         break;
+       case 'G':
+         i= qh_strtol (s, &t);
+         if (qh GOODpoint)
+           fprintf (qh ferr, "qhull warning: good point already defined for option 'QGn'.  Ignored\n");
+          else if (s == t)
+           fprintf (qh ferr, "qhull warning: missing good point id for option 'QGn'.  Ignored\n");
+         else if (i < 0 || *s == '-') {
+           qh GOODpoint= i-1;
+           qh_option ("QGood-if-dont-see-point", &i, NULL);
+         }else {
+           qh GOODpoint= i+1;
+           qh_option ("QGood-if-see-point", &i, NULL);
+         }
+         s= t;
+         break;
+       case 'J':
+          if (!isdigit(*s) && *s != '-')
+           qh JOGGLEmax= 0.0;
+         else {
+           qh JOGGLEmax= (realT) qh_strtod (s, &s);
+            qh_option ("QJoggle", NULL, &qh JOGGLEmax);
+         }
+         break;
+       case 'R':
+          if (!isdigit(*s) && *s != '-')
+           fprintf (qh ferr, "qhull warning: missing random seed for option 'QRn'.  Ignored\n");
+         else {
+           qh ROTATErandom= i= qh_strtol(s, &s);
+           if (i > 0)
+             qh_option ("QRotate-id", &i, NULL );
+           else if (i < -1)
+             qh_option ("QRandom-seed", &i, NULL );
+          }
+         break;
+       case 'V':
+         i= qh_strtol (s, &t);
+         if (qh GOODvertex)
+           fprintf (qh ferr, "qhull warning: good verte