1112 lines
37 KiB
C++
1112 lines
37 KiB
C++
/*<html><pre> -<a href="qh-user.htm"
|
|
>-------------------------------</a><a name="TOP">-</a>
|
|
|
|
user.h
|
|
user redefinable constants
|
|
|
|
for each source file, user.h is included first
|
|
|
|
see qh-user.htm. see COPYING for copyright information.
|
|
|
|
See user.c for sample code.
|
|
|
|
before reading any code, review libqhull.h for data structure definitions
|
|
and the "qh" macro.
|
|
|
|
Sections:
|
|
============= qhull library constants ======================
|
|
============= data types and configuration macros ==========
|
|
============= performance related constants ================
|
|
============= memory constants =============================
|
|
============= joggle constants =============================
|
|
============= conditional compilation ======================
|
|
============= merge constants ==============================
|
|
============= Microsoft DevStudio ==========================
|
|
|
|
Code flags --
|
|
NOerrors -- the code does not call qh_errexit()
|
|
WARN64 -- the code may be incompatible with 64-bit pointers
|
|
|
|
*/
|
|
|
|
#include <float.h>
|
|
#include <limits.h>
|
|
#include <time.h>
|
|
|
|
#ifndef qhDEFuser
|
|
#define qhDEFuser 1
|
|
|
|
/* Derived from Qt's corelib/global/qglobal.h */
|
|
#if !defined(SAG_COM) && !defined(__CYGWIN__) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
|
|
# define QHULL_OS_WIN
|
|
#elif defined(__MWERKS__) && defined(__INTEL__) /* Metrowerks discontinued before the release of Intel Macs */
|
|
# define QHULL_OS_WIN
|
|
#endif
|
|
|
|
/*============================================================*/
|
|
/*============= qhull library constants ======================*/
|
|
/*============================================================*/
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="filenamelen">-</a>
|
|
|
|
FILENAMElen -- max length for TI and TO filenames
|
|
|
|
*/
|
|
|
|
#define qh_FILENAMElen 500
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="msgcode">-</a>
|
|
|
|
msgcode -- Unique message codes for qh_fprintf
|
|
|
|
If add new messages, assign these values and increment in user.h and user.h
|
|
See QhullError.h for 10000 error codes.
|
|
Cannot use '0031' since it would be octal
|
|
|
|
def counters = [31/32/33/38, 1067, 2113, 3079, 4097, 5006,
|
|
6429, 7027/7028/7035/7068/7070/7102, 8163, 9428, 10000, 11034]
|
|
|
|
See: qh_ERR* [libqhull.h]
|
|
*/
|
|
|
|
#define MSG_TRACE0 0 /* always include if logging ('Tn') */
|
|
#define MSG_TRACE1 1000
|
|
#define MSG_TRACE2 2000
|
|
#define MSG_TRACE3 3000
|
|
#define MSG_TRACE4 4000
|
|
#define MSG_TRACE5 5000
|
|
#define MSG_ERROR 6000 /* errors written to qh.ferr */
|
|
#define MSG_WARNING 7000
|
|
#define MSG_STDERR 8000 /* log messages Written to qh.ferr */
|
|
#define MSG_OUTPUT 9000
|
|
#define MSG_QHULL_ERROR 10000 /* errors thrown by QhullError.cpp (QHULLlastError is in QhullError.h) */
|
|
#define MSG_FIX 11000 /* Document as 'QH11... FIX: ...' */
|
|
#define MSG_MAXLEN 3000 /* qh_printhelp_degenerate() in user.c */
|
|
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="qh_OPTIONline">-</a>
|
|
|
|
qh_OPTIONline -- max length of an option line 'FO'
|
|
*/
|
|
#define qh_OPTIONline 80
|
|
|
|
/*============================================================*/
|
|
/*============= 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
|
|
helpful 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="countT">-</a>
|
|
|
|
countT
|
|
The type for counts and identifiers (e.g., the number of points, vertex identifiers)
|
|
Currently used by C++ code-only. Decided against using it for setT because most sets are small.
|
|
|
|
Defined as 'int' for C-code compatibility and QH11026
|
|
|
|
QH11026 FIX: countT may be defined as a 'unsigned int', but several code issues need to be solved first. See countT in Changes.txt
|
|
*/
|
|
|
|
#ifndef DEFcountT
|
|
#define DEFcountT 1
|
|
typedef int countT;
|
|
#endif
|
|
#define COUNTmax INT_MAX
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="qh_POINTSmax">-</a>
|
|
|
|
qh_POINTSmax
|
|
Maximum number of points for qh.num_points and point allocation in qh_readpoints
|
|
*/
|
|
#define qh_POINTSmax (INT_MAX-16)
|
|
|
|
/*-<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. By default,
|
|
<time.h> defines clock_t as 'long'
|
|
|
|
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, may be converted to approximate double */
|
|
#define qh_SECticks CLOCKS_PER_SECOND
|
|
|
|
#elif defined(CLOCKS_PER_SEC)
|
|
#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock, may be converted to approximate double */
|
|
#define qh_SECticks CLOCKS_PER_SEC
|
|
|
|
#elif defined(CLK_TCK)
|
|
#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock, may be converted to approximate double */
|
|
#define qh_SECticks CLK_TCK
|
|
|
|
#else
|
|
#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock, may be converted to approximate double */
|
|
#define qh_SECticks 1E6
|
|
#endif
|
|
|
|
#elif (qh_CLOCKtype == 2)
|
|
#define qh_CPUclock qh_clock() /* return CPU clock, may be converted to approximate double */
|
|
#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 int)seed);
|
|
|
|
#elif (qh_RANDOMtype == 3)
|
|
#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, Sun */
|
|
#define qh_RANDOMint rand()
|
|
#define qh_RANDOMseed_(seed) srand((unsigned int)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
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="RANDOMdist">-</a>
|
|
|
|
qh_RANDOMdist
|
|
define for random perturbation of qh_distplane and qh_setfacetplane (qh.RANDOMdist, 'QRn')
|
|
|
|
For testing qh.DISTround. Qhull should not depend on computations always producing the same roundoff error
|
|
|
|
#define qh_RANDOMdist 1e-13
|
|
*/
|
|
|
|
/*============================================================*/
|
|
/*============= joggle constants =============================*/
|
|
/*============================================================*/
|
|
|
|
/*-<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 50
|
|
|
|
/*============================================================*/
|
|
/*============= 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
|
|
|
|
/*============================================================*/
|
|
/*============= 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 [fmax_() is defined in geom.h]
|
|
#define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *))
|
|
*/
|
|
#define qh_MEMalign ((int)(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)
|
|
|
|
qh_DEFAULTbox
|
|
default box size for integer coorindate (rbox only)
|
|
*/
|
|
#define qh_DEFAULTbox 0.5
|
|
#define qh_DEFAULTzbox 1e6
|
|
|
|
/*============================================================*/
|
|
/*============= 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__ && __INTEL__
|
|
defined by Metrowerks when compiling for Windows (not Intel-based Macintosh)
|
|
|
|
__MWERKS__ && __POWERPC__
|
|
defined by Metrowerks when compiling for PowerPC-based 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
|
|
For MSVC compiles, use qhull-exports-nomerge.def instead of qhull-exports.def
|
|
|
|
notes:
|
|
This saves about 25% space, 30% space in combination with qh_NOtrace,
|
|
and 36% with qh_NOtrace and qh_KEEPstatistics 0
|
|
|
|
Unless option 'Q0' is used
|
|
qh_NOmerge sets 'QJ' to avoid precision errors
|
|
|
|
see:
|
|
<a href="mem.h#NOmem">qh_NOmem</a> in mem.h
|
|
|
|
see user.c/user_eg.c for removing io.o
|
|
|
|
#define qh_NOmerge
|
|
*/
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="NOtrace">-</a>
|
|
|
|
qh_NOtrace
|
|
no tracing if defined
|
|
disables 'Tn', 'TMn', 'TPn' and 'TWn'
|
|
override with 'Qw' for qh_addpoint tracing and various other items
|
|
|
|
notes:
|
|
This saves about 15% space.
|
|
Removes all traceN((...)) code and substantial sections of qh.IStracing code
|
|
|
|
#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()
|
|
[2010, gcc] costs about 4% in time and 4% in space
|
|
[2003, msvc] 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
|
|
|
|
For msvc, define qh_QHpointer_dllimport or qh_dllimport for qh_qh as __declspec(dllimport) [libqhull.h]
|
|
|
|
notes:
|
|
[jan'16] qh_QHpointer is deprecated for Qhull. Use libqhull_r instead.
|
|
all global variables for qhull are in qh, qhmem, and qhstat
|
|
qh is defined in libqhull.h
|
|
qhmem is defined in mem.h
|
|
qhstat is defined in stat.h
|
|
|
|
#define qh_QHpointer 1
|
|
*/
|
|
|
|
#ifdef qh_QHpointer
|
|
#ifdef qh_dllimport
|
|
#error QH6207 Qhull error: Define qh_QHpointer_dllimport instead of qh_dllimport with qh_QHpointer
|
|
#endif
|
|
#else
|
|
#define qh_QHpointer 0
|
|
#ifdef qh_QHpointer_dllimport
|
|
#error QH6234 Qhull error: Define qh_dllimport instead of qh_QHpointer_dllimport when qh_QHpointer is not defined
|
|
#endif
|
|
#endif
|
|
#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 them. They effect the performance of facet merging.
|
|
*/
|
|
|
|
/*-<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="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="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="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="MAXcheckpoint">-</a>
|
|
|
|
qh_MAXcheckpoint
|
|
Report up to qh_MAXcheckpoint errors per facet in qh_check_point ('Tv')
|
|
*/
|
|
#define qh_MAXcheckpoint 10
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="MAXcoplanarcentrum">-</a>
|
|
|
|
qh_MAXcoplanarcentrum
|
|
if pre-merging with qh.MERGEexact ('Qx') and f.nummerge > qh_MAXcoplanarcentrum
|
|
use f.maxoutside instead of qh.centrum_radius for coplanarity testing
|
|
|
|
notes:
|
|
see qh_test_nonsimplicial_merges
|
|
with qh.MERGEexact, a coplanar ridge is ignored until post-merging
|
|
otherwise a large facet with many merges may take all the facets
|
|
*/
|
|
#define qh_MAXcoplanarcentrum 10
|
|
|
|
/*-<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="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="RATIOconcavehorizon">-</a>
|
|
|
|
qh_RATIOconcavehorizon
|
|
ratio of horizon vertex distance to max_outside for concave, twisted new facets in qh_test_nonsimplicial_merge
|
|
if too small, end up with vertices far below merged facets
|
|
*/
|
|
#define qh_RATIOconcavehorizon 20.0
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="RATIOconvexmerge">-</a>
|
|
|
|
qh_RATIOconvexmerge
|
|
ratio of vertex distance to qh.min_vertex for clearly convex new facets in qh_test_nonsimplicial_merge
|
|
|
|
notes:
|
|
must be convex for MRGtwisted
|
|
*/
|
|
#define qh_RATIOconvexmerge 10.0
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="RATIOcoplanarapex">-</a>
|
|
|
|
qh_RATIOcoplanarapex
|
|
ratio of best distance for coplanar apex vs. vertex merge in qh_getpinchedmerges
|
|
|
|
notes:
|
|
A coplanar apex always works, while a vertex merge may fail
|
|
*/
|
|
#define qh_RATIOcoplanarapex 3.0
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="RATIOcoplanaroutside">-</a>
|
|
|
|
qh_RATIOcoplanaroutside
|
|
qh.MAXoutside ratio to repartition a coplanar point in qh_partitioncoplanar and qh_check_maxout
|
|
|
|
notes:
|
|
combines several tests, see qh_partitioncoplanar
|
|
|
|
*/
|
|
#define qh_RATIOcoplanaroutside 30.0
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="RATIOmaxsimplex">-</a>
|
|
|
|
qh_RATIOmaxsimplex
|
|
ratio of max determinate to estimated determinate for searching all points in qh_maxsimplex
|
|
|
|
notes:
|
|
As each point is added to the simplex, the max determinate is should approximate the previous determinate * qh.MAXwidth
|
|
If maxdet is significantly less, the simplex may not be full-dimensional.
|
|
If so, all points are searched, stopping at 10 times qh_RATIOmaxsimplex
|
|
*/
|
|
#define qh_RATIOmaxsimplex 1.0e-3
|
|
|
|
/*-<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, nearly incident points
|
|
*/
|
|
#define qh_RATIOnearinside 5
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="RATIOpinchedsubridge">-</a>
|
|
|
|
qh_RATIOpinchedsubridge
|
|
ratio to qh.ONEmerge to accept vertices in qh_findbest_pinchedvertex
|
|
skips search of neighboring vertices
|
|
facet width may increase by this ratio
|
|
*/
|
|
#define qh_RATIOpinchedsubridge 10.0
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="RATIOtrypinched">-</a>
|
|
|
|
qh_RATIOtrypinched
|
|
ratio to qh.ONEmerge to try qh_getpinchedmerges in qh_buildcone_mergepinched
|
|
otherwise a duplicate ridge will increase facet width by this amount
|
|
*/
|
|
#define qh_RATIOtrypinched 4.0
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="RATIOtwisted">-</a>
|
|
|
|
qh_RATIOtwisted
|
|
maximum ratio to qh.ONEmerge to merge twisted facets in qh_merge_twisted
|
|
*/
|
|
#define qh_RATIOtwisted 20.0
|
|
|
|
/*-<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.
|
|
increases minsearch if ischeckmax and more than 100 neighbors (is_5x_minsearch)
|
|
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="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="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="WIDEduplicate">-</a>
|
|
|
|
qh_WIDEduplicate
|
|
merge ratio for errexit from qh_forcedmerges due to duplicate ridge
|
|
Override with option Q12-allow-wide
|
|
|
|
Notes:
|
|
Merging a duplicate ridge can lead to very wide facets.
|
|
*/
|
|
#define qh_WIDEduplicate 100
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="WIDEdupridge">-</a>
|
|
|
|
qh_WIDEdupridge
|
|
Merge ratio for selecting a forced dupridge merge
|
|
|
|
Notes:
|
|
Merging a dupridge can lead to very wide facets.
|
|
*/
|
|
#define qh_WIDEdupridge 50
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="WIDEmaxoutside">-</a>
|
|
|
|
qh_WIDEmaxoutside
|
|
Precision ratio for maximum increase for qh.max_outside in qh_check_maxout
|
|
Precision errors while constructing the hull, may lead to very wide facets when checked in qh_check_maxout
|
|
Nearly incident points in 4-d and higher is the most likely culprit
|
|
Skip qh_check_maxout with 'Q5' (no-check-outer)
|
|
Do not error with option 'Q12' (allow-wide)
|
|
Do not warn with options 'Q12 Pp'
|
|
*/
|
|
#define qh_WIDEmaxoutside 100
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="WIDEmaxoutside2">-</a>
|
|
|
|
qh_WIDEmaxoutside2
|
|
Precision ratio for maximum qh.max_outside in qh_check_maxout
|
|
Skip qh_check_maxout with 'Q5' no-check-outer
|
|
Do not error with option 'Q12' allow-wide
|
|
*/
|
|
#define qh_WIDEmaxoutside2 (10*qh_WIDEmaxoutside)
|
|
|
|
|
|
/*-<a href="qh-user.htm#TOC"
|
|
>--------------------------------</a><a name="WIDEpinched">-</a>
|
|
|
|
qh_WIDEpinched
|
|
Merge ratio for distance between pinched vertices compared to current facet width for qh_getpinchedmerges and qh_next_vertexmerge
|
|
Reports warning and merges duplicate ridges instead
|
|
Enable these attempts with option Q14 merge-pinched-vertices
|
|
|
|
notes:
|
|
Merging pinched vertices should prevent duplicate ridges (see qh_WIDEduplicate)
|
|
Merging the duplicate ridges may be better than merging the pinched vertices
|
|
Found up to 45x ratio for qh_pointdist -- for ((i=1; i<20; i++)); do rbox 175 C1,6e-13 t | qhull d T4 2>&1 | tee x.1 | grep -E 'QH|non-simplicial|Statis|pinched'; done
|
|
Actual distance to facets is a third to a tenth of the qh_pointdist (T1)
|
|
*/
|
|
#define qh_WIDEpinched 100
|
|
|
|
/*-<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
|
|
|
|
/*============================================================*/
|
|
/*============= Microsoft DevStudio ==========================*/
|
|
/*============================================================*/
|
|
|
|
/*
|
|
Finding Memory Leaks Using the CRT Library
|
|
https://msdn.microsoft.com/en-us/library/x98tx3cf(v=vs.100).aspx
|
|
|
|
Reports enabled in qh_lib_check for Debug window and stderr
|
|
|
|
From 2005=>msvcr80d, 2010=>msvcr100d, 2012=>msvcr110d
|
|
|
|
Watch: {,,msvcr80d.dll}_crtBreakAlloc Value from {n} in the leak report
|
|
_CrtSetBreakAlloc(689); // qh_lib_check() [global.c]
|
|
|
|
Examples
|
|
http://free-cad.sourceforge.net/SrcDocu/d2/d7f/MemDebug_8cpp_source.html
|
|
https://github.com/illlust/Game/blob/master/library/MemoryLeak.cpp
|
|
*/
|
|
#if 0 /* off (0) by default for QHULL_CRTDBG */
|
|
#define QHULL_CRTDBG
|
|
#endif
|
|
|
|
#if defined(_MSC_VER) && defined(_DEBUG) && defined(QHULL_CRTDBG)
|
|
#define _CRTDBG_MAP_ALLOC
|
|
#include <stdlib.h>
|
|
#include <crtdbg.h>
|
|
#endif
|
|
|
|
#endif /* qh_DEFuser */
|