Add graph references
This commit is contained in:
+12
@@ -0,0 +1,12 @@
|
||||
Modifying from https://github.com/qhull/qhull on commit d1c2fc0caa5f644f3a0f220290d4a868c68ed4f6
|
||||
|
||||
Changed `userprintf_r.c` to not print when passed a null pointer as file handle.
|
||||
|
||||
Changed `usermem_r.c` to not reference `exit()`. Even though this `exit()` is never called, it is necessary to keep igraph free of any references to it to satisfy CRAN requirements and comply with Debian guidelines.
|
||||
|
||||
Changed the following settings in `user_r.h`:
|
||||
|
||||
- `#define qh_KEEPstatistics 0`, do not incude statistics gathering code
|
||||
- `#define qh_NOtrace`, do not include tracing code
|
||||
|
||||
Patched with https://github.com/qhull/qhull/pull/165.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Declare the files needed to compile our vendored plfit copy
|
||||
add_library(
|
||||
qhull_vendored
|
||||
OBJECT
|
||||
EXCLUDE_FROM_ALL
|
||||
libqhull_r/accessors_r.c
|
||||
libqhull_r/geom_r.c
|
||||
libqhull_r/geom2_r.c
|
||||
libqhull_r/global_r.c
|
||||
libqhull_r/io_r.c
|
||||
libqhull_r/libqhull_r.c
|
||||
libqhull_r/mem_r.c
|
||||
libqhull_r/merge_r.c
|
||||
libqhull_r/poly_r.c
|
||||
libqhull_r/poly2_r.c
|
||||
libqhull_r/qset_r.c
|
||||
libqhull_r/random_r.c
|
||||
libqhull_r/rboxlib_r.c
|
||||
libqhull_r/stat_r.c
|
||||
libqhull_r/user_r.c
|
||||
libqhull_r/usermem_r.c
|
||||
libqhull_r/userprintf_r.c
|
||||
libqhull_r/userprintf_rbox_r.c
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
qhull_vendored
|
||||
PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
${PROJECT_BINARY_DIR}/include
|
||||
#PUBLIC
|
||||
#${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set_property(TARGET qhull_vendored PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
# Since these are included as object files, they should call the
|
||||
# function as is (without visibility specification)
|
||||
target_compile_definitions(qhull_vendored PRIVATE IGRAPH_STATIC)
|
||||
|
||||
use_all_warnings(qhull_vendored)
|
||||
|
||||
target_compile_options(
|
||||
qhull_vendored PRIVATE
|
||||
$<$<C_COMPILER_ID:GCC,Clang,AppleClang,IntelLLVM>:-Wno-unused-variable>
|
||||
)
|
||||
@@ -0,0 +1,39 @@
|
||||
Qhull, Copyright (c) 1993-2020
|
||||
|
||||
C.B. Barber
|
||||
Arlington, MA
|
||||
|
||||
and
|
||||
|
||||
The National Science and Technology Research Center for
|
||||
Computation and Visualization of Geometric Structures
|
||||
(The Geometry Center)
|
||||
University of Minnesota
|
||||
|
||||
email: qhull@qhull.org
|
||||
|
||||
This software includes Qhull from C.B. Barber and The Geometry Center.
|
||||
Files derived from Qhull 1.0 are copyrighted by the Geometry Center. The
|
||||
remaining files are copyrighted by C.B. Barber. Qhull is free software
|
||||
and may be obtained via http from www.qhull.org. 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@qhull.org; the authors may or may not act on them as
|
||||
they desire.
|
||||
+720
@@ -0,0 +1,720 @@
|
||||
Name
|
||||
|
||||
qhull, rbox 2020.2 2020/08/31 (8.0.2)
|
||||
|
||||
Convex hull, Delaunay triangulation, Voronoi diagrams, Halfspace intersection
|
||||
|
||||
Documentation:
|
||||
html/index.htm
|
||||
<http://www.qhull.org/html>
|
||||
|
||||
Available from:
|
||||
<http://www.qhull.org>
|
||||
<http://www.qhull.org/download>
|
||||
<http://github.com/qhull/qhull/wiki> (git@github.com:qhull/qhull.git)
|
||||
|
||||
News and a paper:
|
||||
<http://www.qhull.org/news>
|
||||
<http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.117.405>
|
||||
|
||||
Version 1 (simplicial only):
|
||||
<http://www.qhull.org/download/qhull-1.0.tar.gz>
|
||||
|
||||
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. It comes with examples and test scripts.
|
||||
|
||||
Qhull's C++ interface uses the STL. The C++ test program uses QTestLib
|
||||
from the Qt Framework.
|
||||
|
||||
Qhull is copyrighted software. Please read COPYING.txt and REGISTER.txt
|
||||
before using or distributing Qhull.
|
||||
|
||||
To cite Qhull, please use
|
||||
|
||||
Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The Quickhull
|
||||
algorithm for convex hulls," ACM Trans. on Mathematical Software,
|
||||
22(4):469-483, Dec 1996, http://www.qhull.org.
|
||||
|
||||
To modify Qhull, particularly the C++ interface
|
||||
|
||||
Qhull is on GitHub
|
||||
(http://github.com/qhull/qhull/wiki, git@github.com:qhull/qhull.git)
|
||||
|
||||
For internal documentation, see html/qh-code.htm
|
||||
|
||||
To install Qhull
|
||||
|
||||
Qhull is precompiled for Windows 32-bit, otherwise it needs compilation.
|
||||
|
||||
Qhull includes Makefiles for gcc and other targets, CMakeLists.txt for CMake,
|
||||
.sln/.vcproj/.vcxproj files for Microsoft Visual Studio, and .pro files
|
||||
for Qt Creator. It compiles under Windows with mingw.
|
||||
(<https://github.com/qhull/qhull/wiki/Qhull-build-systems>)
|
||||
|
||||
Install and build instructions follow.
|
||||
|
||||
See the end of this document for a list of distributed files.
|
||||
|
||||
------------------
|
||||
Index
|
||||
|
||||
Installing Qhull on Windows 10, 8, 7 (32- or 64-bit), Windows XP, and Windows NT
|
||||
Installing Qhull on Unix with gcc
|
||||
Installing Qhull with CMake 2.6 or later
|
||||
Installing Qhull with Qt
|
||||
Working with Qhull's C++ interface
|
||||
Calling Qhull from C programs
|
||||
Compiling Qhull with Microsoft Visual C++
|
||||
Compiling Qhull with Qt Creator
|
||||
Compiling Qhull with mingw/gcc on Windows
|
||||
Compiling Qhull with cygwin on Windows
|
||||
Compiling from Makfile without gcc
|
||||
Compiling on other machines and compilers
|
||||
Distributed files
|
||||
Authors
|
||||
|
||||
------------------
|
||||
Installing Qhull on Windows 10, 8, 7 (32- or 64-bit), Windows XP, and Windows NT
|
||||
|
||||
The zip file contains rbox.exe, qhull.exe, qconvex.exe, qdelaunay.exe,
|
||||
qhalf.exe, qvoronoi.exe, testqset.exe, user_eg*.exe, documentation files,
|
||||
and source files. Qhull.exe and user-eg3.exe are compiled with the reentrant
|
||||
library while the other executables use the non-reentrant library.
|
||||
|
||||
To install Qhull:
|
||||
- Unzip the files into a directory (e.g., named 'qhull')
|
||||
- Click on QHULL-GO or open a command window into Qhull's bin directory.
|
||||
- Test with 'rbox D4 | qhull'
|
||||
|
||||
To uninstall Qhull
|
||||
- Delete the qhull directory
|
||||
|
||||
To learn about Qhull:
|
||||
- Execute 'qconvex' for a synopsis and examples.
|
||||
Or 'qconvex --help' or 'qconvex -?'
|
||||
- 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'.
|
||||
- Browse the documentation: qhull\html\index.htm
|
||||
- If an error occurs, Windows sends the error to stdout instead of stderr.
|
||||
Use 'TO xxx' to send normal output to xxx
|
||||
|
||||
To improve the command window
|
||||
- Double-click the window bar to increase the size of the window
|
||||
- Right-click the window bar
|
||||
- Select Properties
|
||||
- Check QuickEdit Mode
|
||||
Select text with right-click or Enter
|
||||
Paste text with right-click
|
||||
- Change Font to Lucinda Console
|
||||
- Change Layout to Screen Buffer Height 999, Window Size Height 55
|
||||
- Change Colors to Screen Background White, Screen Text Black
|
||||
- Click OK
|
||||
- Select 'Modify shortcut that started this window', then OK
|
||||
|
||||
If you regularly use qhull on a Windows host, install a bash shell such as
|
||||
https://gitforwindows.org/ # based on MSYS2
|
||||
https://github.com/git-for-windows/git/wiki
|
||||
http://www.msys2.org/
|
||||
https://github.com/msys2/msys2/wiki
|
||||
[mar'19] Git for Windows v2.21 requires 'qhull --help'
|
||||
Install in C:\Git\... # Not 'Program Files\...' otherwise './configure && make' fails
|
||||
www.cygwin.com
|
||||
www.mingw.org/wiki/msys # for Windows XP
|
||||
Road Bash (www.qhull.org/bash) # based on MSYS
|
||||
|
||||
------------------
|
||||
Installing Qhull on Unix with gcc
|
||||
|
||||
To build Qhull, static libraries, shared library, and C++ interface
|
||||
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
|
||||
- make
|
||||
- export LD_LIBRARY_PATH=$PWD/lib:$LD_LIBRARY_PATH
|
||||
- make test
|
||||
|
||||
'make install' installs Qhull at '/usr/local/'. It installs pkg-config files
|
||||
at '/usr/local/lib/pkgconfig'. Change the install directory with DESTDIR and PREFIX.
|
||||
|
||||
To build 32-bit Qhull on a 64-bit host (uses 33% less memory in 4-d)
|
||||
- make new M32=-m32
|
||||
|
||||
To build 32-bit Qhull without -fpic (may be faster, but shared library may fail)
|
||||
- make new M32=-m32 FPIC=
|
||||
|
||||
The Makefiles may be edited for other compilers.
|
||||
If 'testqset' exits with an error, qhull is broken
|
||||
|
||||
A simple Makefile for Qhull is in src/libqhull and src/libqhull_r.
|
||||
To build the Qhull executables and libqhullstatic
|
||||
- Extract Qhull from qhull...tgz or qhull...zip
|
||||
- cd src/libqhull_r # cd src/libqhull
|
||||
- make
|
||||
|
||||
|
||||
------------------
|
||||
Installing Qhull with CMake 2.6 or later
|
||||
|
||||
See CMakeLists.txt for examples and further build instructions
|
||||
|
||||
To build Qhull, static libraries, shared library, and C++ interface
|
||||
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
|
||||
- cd build
|
||||
- cmake --help # List build generators
|
||||
- cmake -G "<generator>" .. # e.g., for MINGW-w64 -- cmake -G "MSYS Makefiles" ..
|
||||
- cmake ..
|
||||
- make
|
||||
- ctest
|
||||
- make install # If MSYS or UNIX, default CMAKE_INSTALL_PREFIX is '/usr/local'
|
||||
# otherwise if WINDOWS, installs to ../bin, ../include, and ../lib
|
||||
- make uninstall # Delete the files in install_manifest.txt
|
||||
|
||||
The ".." is important. It refers to the parent directory (i.e., qhull/)
|
||||
|
||||
CMake installs lib/pkgconfig/qhull*.pc for use with pkg-config
|
||||
|
||||
If CMAKE_INSTALL_PREFIX is C:/Program Files/qhull, you may need to give 'Users' "full control"
|
||||
to qhull's sub-directories: bin, doc, include, lib, and man (folder > Properties > Security > Edit > Users).
|
||||
|
||||
On Windows, CMake's 64-bit generators have a "Win64" tag. Qhull's data structures
|
||||
are substantial larger as 64-bit code than as 32-bit code. This may slow down Qhull.
|
||||
|
||||
If cmake fails with "No CMAKE_C_COMPILER could be found"
|
||||
- cmake was not able to find the build environment specified by -G "..."
|
||||
|
||||
If cmake's gcc smoketest fails after a Windows update
|
||||
- Reinstall MINGW-w64 and delete build/CMakeCache.txt. A Windows update can break gcc process creation for cc1.
|
||||
|
||||
------------------
|
||||
Installing Qhull with Qt
|
||||
|
||||
To build Qhull, including its C++ test program (qhulltest)
|
||||
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
|
||||
- Load src/qhull-all.pro into QtCreator
|
||||
- Configure the project to use a Shadow build at the same level as 'src', 'bin', and 'lib'
|
||||
If, instead, the shadow build is a subdirectory of 'build', Qt Creator will install Qhull in 'build/bin' and 'build/lib'
|
||||
- Build
|
||||
|
||||
- Build qhulltest with a C++11 or later compiler
|
||||
- qhulltest depends on shared libraries QtCore.a and QtTest.a. They may need to be copied
|
||||
into the bin directory. On Windows, copy Qt5Core.dll and Qt5Test.dll, e.g., /qt/5.11.2/msvc2017_64/bin
|
||||
- If qhulltest fails with exit status 127 and no error message,
|
||||
check for missing Q5Core.dll and Qt5Test.dll
|
||||
|
||||
------------------
|
||||
Working with Qhull's C++ interface
|
||||
|
||||
See html/qh-code.htm#cpp for calling Qhull from C++ programs
|
||||
|
||||
Class and method documentation is limited
|
||||
|
||||
See html/qh-code.htm#reentrant for converting from Qhull-2012
|
||||
|
||||
Examples of using the C++ interface
|
||||
user_eg3_r.cpp
|
||||
qhulltest/*_test.cpp
|
||||
|
||||
Qhull's C++ interface is likely to change. Stay current with GitHub.
|
||||
|
||||
To clone Qhull's next branch from http://github.com/qhull/qhull/wiki
|
||||
git init
|
||||
git clone git@github.com:qhull/qhull.git
|
||||
cd qhull
|
||||
git checkout next
|
||||
...
|
||||
git pull origin next
|
||||
|
||||
Compile qhullcpp and libqhullstatic_r with the same compiler. Both libraries
|
||||
use the C routines setjmp() and longjmp() for error handling. They must
|
||||
be compiled with the same compiler.
|
||||
|
||||
Qhull provides pkg-config support with build/qhull.pc.in and lib/pkgconfig/qhull*.pc
|
||||
With back-ticks, you can compile your C++ program with the Qhull libraries:
|
||||
g++ `pkg-config --cflags --libs qhullcpp qhullstatic_r` -o my_app my_app.cpp
|
||||
or
|
||||
g++ `pkg-config --cflags --libs qhullcpp qhull_r` -o my_app my_app.cpp
|
||||
|
||||
qhullcpp must be linked before qhull_r, otherwise the linker reports
|
||||
an error -- "QhullUser ... multiple definition of `qh_fprintf'"
|
||||
|
||||
------------------
|
||||
Calling Qhull from C programs
|
||||
|
||||
See html/qh-code.htm#library for calling Qhull from C programs
|
||||
|
||||
Qhull provides pkg-config support with build/qhull.pc.in and lib/pkgconfig/qhull*.pc
|
||||
With back-ticks, you can compile your C program with the Qhull library
|
||||
gcc `pkg-config --cflags --libs qhull_r` -o my_app my_app.c
|
||||
|
||||
See html/qh-code.htm#reentrant for converting from Qhull-2012
|
||||
|
||||
Warning: You will need to understand Qhull's data structures and read the
|
||||
code. Most users will find it easier to call Qhull as an external command.
|
||||
|
||||
The reentrant 'C' code (src/libqhull_r), passes a pointer to qhT
|
||||
to most Qhull routines. This allows multiple instances of Qhull to run
|
||||
at the same time. It simplifies the C++ interface.
|
||||
|
||||
The non-reentrant 'C' code (src/libqhull) looks unusual. It refers to
|
||||
Qhull's global data structure, qhT, through a 'qh' macro (e.g., 'qh ferr').
|
||||
This allows the same code to use static memory or heap memory.
|
||||
If qh_QHpointer is defined, qh_qh is a pointer to an allocated qhT;
|
||||
otherwise qh_qh is a global static data structure of type qhT.
|
||||
|
||||
------------------
|
||||
Compiling Qhull with Microsoft Visual C++
|
||||
|
||||
To compile 32-bit Qhull with Microsoft Visual C++ 2010 and later
|
||||
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
|
||||
- Load solution build/qhull-32.sln
|
||||
- Right-click 'Retarget solution' from toolset v110 to your Platform Toolset
|
||||
File > Save All
|
||||
- Build target 'Win32'
|
||||
- Project qhulltest requires Qt for DevStudio (http://www.qt.io)
|
||||
Set the QTDIR environment variable to your Qt directory (e.g., c:/qt/5.2.0/5.2.0/msvc2012)
|
||||
If QTDIR is incorrect, precompile will fail with 'Can not locate the file specified'
|
||||
- Copy Qt shared libraries, QtCore.dll and QtTest.dll, into the bin directory
|
||||
|
||||
To compile 64-bit Qhull with Microsoft Visual C++ 2010 and later
|
||||
- 64-bit Qhull has larger data structures due to 64-bit pointers. This may slow down Qhull.
|
||||
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
|
||||
- Load solution build/qhull-64.sln
|
||||
- Right-click 'Retarget solution' from toolset v110 to your Platform Toolset
|
||||
File > Save All
|
||||
- Build target 'x64'
|
||||
- If build as 32-bit fails, use solution build/qhull-32.sln
|
||||
- Project qhulltest requires Qt for DevStudio (http://www.qt.io)
|
||||
Set the QTDIR environment variable to your Qt directory (e.g., c:/qt/5.2.0/5.2.0/msvc2012_64)
|
||||
If QTDIR is incorrect, precompile will fail with 'Can not locate the file specified'
|
||||
|
||||
If error -- MSB8020: The build tools for Visual Studio 2012 (Platform Toolset = 'v110') cannot be found.
|
||||
- 'Project > Retarget solution' for both qhull-32.sln and qhull-64.sln
|
||||
- 'File > Open' your preferred solution (qhull-32.sln or qhull-64.sln)
|
||||
- 'Save All' both projects
|
||||
- DevStudio may need a restart
|
||||
|
||||
To compile Qhull with Microsoft Visual C++ 2005 (vcproj files)
|
||||
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
|
||||
- Load solution build/qhull.sln
|
||||
- Build target 'win32' (not 'x64')
|
||||
- Project qhulltest requires Qt for DevStudio (http://www.qt.io)
|
||||
Set the QTDIR environment variable to your Qt directory (e.g., c:/qt/4.7.4)
|
||||
If QTDIR is incorrect, precompile will fail with 'Can not locate the file specified'
|
||||
|
||||
------------------
|
||||
Compiling Qhull with Qt Creator
|
||||
|
||||
Qt (http://www.qt.io) is a C++ framework for Windows, Linux, and Macintosh
|
||||
|
||||
Qhull uses QTestLib to test qhull's C++ interface (see src/qhulltest/)
|
||||
|
||||
To compile Qhull with Qt Creator
|
||||
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
|
||||
- Download the Qt SDK
|
||||
- Start Qt Creator
|
||||
- Load src/qhull-all.pro
|
||||
- Configure the project to use a Shadow build at the same level as 'src', 'bin', and 'lib'
|
||||
If, instead, the shadow build is a subdirectory of 'build', Qt Creator will install Qhull in 'build/bin' and 'build/lib'
|
||||
- Build
|
||||
|
||||
- Build qhulltest with a C++11 or later compiler
|
||||
- qhulltest depends on shared libraries QtCore.a and QtTest.a. They may need to be copied
|
||||
into the bin directory. On Windows, copy Qt5Core.dll and Qt5Test.dll, e.g., /qt/5.11.2/msvc2017_64/bin
|
||||
- If qhulltest fails with exit status 127 and no error message,
|
||||
check for missing Q5Core.dll and Qt5Test.dll
|
||||
|
||||
------------------
|
||||
Compiling Qhull with mingw/gcc on Windows
|
||||
|
||||
To compile Qhull with MINGW
|
||||
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
|
||||
- Install GitForWindows (https://gitforwindows.org/)
|
||||
or MSYS2 (http://www.msys2.org/)
|
||||
Install in C:\Git\... # Not 'Program Files\...' otherwise './configure && make' will not work
|
||||
- Install MINGW-w64 with gcc (https://mingw-w64.org/)
|
||||
1) Goto sourceforge -- https://sourceforge.net/projects/mingw-w64/files/
|
||||
2) in folder -- mingw-w64
|
||||
3) download installer -- MinGW-W64-install.exe
|
||||
Run the installer
|
||||
1) Select i686/posix/dwarf
|
||||
2) Install in 'C:\mingw-w64' # Not 'Program Files\...'
|
||||
Rename /c/mingw-w64/mingw32/bin/mingw32-make.exe to make.exe
|
||||
Add the 'C:\mingw-w64\mingw32\bin' directory to your $PATH environment variable
|
||||
Execute 'which make' to check that 'make' is mingw-w64's make
|
||||
- Compile Qhull from the home directory
|
||||
make help
|
||||
make
|
||||
|
||||
Notes
|
||||
- Mingw is included with Qt SDK in qt/Tools/mingw53_32
|
||||
- If you use Windows XP
|
||||
Install Road Bash (http://www.qhull.org/bash) or MSYS (http://www.mingw.org/wiki/msys)
|
||||
Install MINGW (http://mingw.org/)
|
||||
|
||||
------------------
|
||||
Compiling Qhull with cygwin on Windows
|
||||
|
||||
To compile Qhull with cygwin
|
||||
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
|
||||
- Install cygwin (http://www.cygwin.com)
|
||||
- Include packages for gcc, make, ar, and ln
|
||||
- make
|
||||
|
||||
------------------
|
||||
Compiling from Makfile without gcc
|
||||
|
||||
The file, qhull-src.tgz, contains documentation and source files for
|
||||
qhull and rbox.
|
||||
|
||||
To unpack the tgz file
|
||||
- tar zxf qhull-src.tgz
|
||||
- cd qhull
|
||||
- Use qhull/Makefile
|
||||
Simpler Makefiles are qhull/src/libqhull/Makefile and qhull/src/libqhull_r/Makefile
|
||||
|
||||
Compiling qhull and rbox with Makefile
|
||||
- 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 libqhull_r.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 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
|
||||
- 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
|
||||
- to install the programs and their man pages:
|
||||
- define MANDIR and BINDIR
|
||||
- type 'make install'
|
||||
|
||||
- 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)
|
||||
|
||||
------------------
|
||||
Compiling on other machines and compilers
|
||||
|
||||
Qhull may compile with Borland C++ 5.0 bcc32. A Makefile is included.
|
||||
Execute 'cd src/libqhull; make -f Mborland'. If you use the Borland IDE, set
|
||||
the ANSI option in Options:Project:Compiler:Source:Language-compliance.
|
||||
|
||||
Qhull may compile with Borland C++ 4.02 for Win32 and DOS Power Pack.
|
||||
Use 'cd src/libqhull; 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]
|
||||
|
||||
If you have troubles with the memory manager, you can turn it off by
|
||||
defining qh_NOmem in mem.h.
|
||||
|
||||
------------------
|
||||
Distributed files
|
||||
|
||||
README.txt // Instructions for installing Qhull
|
||||
REGISTER.txt // Qhull registration
|
||||
COPYING.txt // Copyright notice
|
||||
QHULL-GO.lnk // Windows icon for eg/qhull-go.bat
|
||||
Announce.txt // Announcement
|
||||
CMakeLists.txt // CMake build file (2.6 or later)
|
||||
File_id.diz // Package descriptor
|
||||
index.htm // Home page
|
||||
Makefile // Makefile for gcc and other compilers
|
||||
qhull*.md5sum // md5sum for all files
|
||||
|
||||
bin/* // Qhull executables and dll (.zip only)
|
||||
build/CMakeModules/CheckLFS.cmake // enables Large File Support in CMake
|
||||
build/config.cmake.in // extract target variables
|
||||
build/qhull.pc.in // pkg-config template for creating lib/pkgconfig/qhull*.pc
|
||||
build/qhull-32.sln // 32-bit DevStudio solution and project files (2010 and later)
|
||||
build/*-32.vcxproj
|
||||
build/qhull-64.sln // 64-bit DevStudio solution and project files (2010 and later)
|
||||
build/*-64.vcxproj
|
||||
build/qhull.sln // DevStudio solution and project files (2005 and 2009)
|
||||
build/*.vcproj
|
||||
build/qhulltest/ // DevStudio project files for qhulltest (C++ and Qt)
|
||||
build/README-build.txt // Contents of build/
|
||||
eg/* // Test scripts and geomview files from q_eg
|
||||
html/index.htm // Manual
|
||||
html/qh-faq.htm // Frequently asked questions
|
||||
html/qh-get.htm // Download page
|
||||
html/qhull-cpp.xml // C++ style notes as a Road FAQ (www.qhull.org/road)
|
||||
src/Changes.txt // Change history for Qhull and rbox
|
||||
src/qhull-all.pro // Qt project
|
||||
|
||||
eg/
|
||||
q_benchmark // shell script for precision and performance benchmark
|
||||
q_benchmark-ok.txt // reviewed output from q_benchmark
|
||||
q_eg // shell script for Geomview examples (eg.01.cube)
|
||||
q_egtest // shell script for Geomview test examples
|
||||
q_test // shell script to test qhull
|
||||
q_test.bat // Windows batch test for QHULL-GO.bat
|
||||
// cd bin; ..\eg\q_test.bat >q_test.x 2>&1
|
||||
q_test-ok.txt // reviewed output from q_test
|
||||
qhulltest-ok.txt // reviewed output from qhulltest (Qt only)
|
||||
make-qhull_qh.sh // shell script to create non-reentrant qhull_qh from reentrant Qhull
|
||||
make-vcproj.sh // shell script to create vcproj and vcxprog files
|
||||
qhull-zip.sh // shell script to create distribution files
|
||||
qtest.sh // shell script for testing and logging qhull
|
||||
|
||||
rbox consists of (bin, html):
|
||||
rbox.exe // Win32 executable (.zip only)
|
||||
rbox.htm // html manual
|
||||
rbox.man // Unix man page
|
||||
rbox.txt
|
||||
|
||||
qhull consists of (bin, html):
|
||||
qconvex.exe // Win32 executables and dlls (.zip download only)
|
||||
qhull.exe // Built with the reentrant library (about 2% slower)
|
||||
qdelaunay.exe
|
||||
qhalf.exe
|
||||
qvoronoi.exe
|
||||
qhull_r.dll
|
||||
qhull-go.bat // command window
|
||||
qconvex.htm // html manual
|
||||
qdelaun.htm
|
||||
qdelau_f.htm
|
||||
qhalf.htm
|
||||
qvoronoi.htm
|
||||
qvoron_f.htm
|
||||
qh-eg.htm
|
||||
qh-code.htm
|
||||
qh-impre.htm
|
||||
index.htm
|
||||
qh-opt*.htm
|
||||
qh-quick.htm
|
||||
qh--*.gif // images for manual
|
||||
normal_voronoi_knauss_oesterle.jpg
|
||||
qh_findbestfacet-drielsma.pdf
|
||||
qhull.man // Unix man page
|
||||
qhull.txt
|
||||
|
||||
bin/
|
||||
msvcr80.dll // Visual C++ redistributable file (.zip download only)
|
||||
|
||||
src/
|
||||
qhull/unix.c // Qhull and rbox applications using non-reentrant libqhullstatic.a
|
||||
rbox/rbox.c
|
||||
qconvex/qconvex.c
|
||||
qhalf/qhalf.c
|
||||
qdelaunay/qdelaunay.c
|
||||
qvoronoi/qvoronoi.c
|
||||
|
||||
qhull/unix_r.c // Qhull and rbox applications using reentrant libqhullstatic_r.a
|
||||
rbox/rbox_r.c
|
||||
qconvex/qconvex_r.c // Qhull applications built with reentrant libqhull_r/Makefile
|
||||
qhalf/qhalf_r.c
|
||||
qdelaunay/qdelaun_r.c
|
||||
qvoronoi/qvoronoi_r.c
|
||||
|
||||
user_eg/user_eg_r.c // example of using qhull_r.dll from a user program
|
||||
user_eg2/user_eg2_r.c // example of using libqhullstatic_r.a from a user program
|
||||
user_eg3/user_eg3_r.cpp // example of Qhull's C++ interface libqhullcpp with libqhullstatic_r.a
|
||||
qhulltest/qhulltest.cpp // Test of Qhull's C++ interface using Qt's QTestLib
|
||||
qhull-*.pri // Include files for Qt projects
|
||||
testqset_r/testqset_r.c // Test of reentrant qset_r.c and mem_r.c
|
||||
testqset/testqset.c // Test of non-rentrant qset.c and mem.c
|
||||
|
||||
src/libqhull
|
||||
libqhull.pro // Qt project for non-rentrant, shared library (qhull.dll)
|
||||
index.htm // design documentation for libqhull
|
||||
qh-*.htm
|
||||
qhull-exports.def // Export Definition files for Visual C++
|
||||
qhull-nomerge-exports.def
|
||||
qhull_p-exports.def
|
||||
qhull_p-nomerge-exports.def
|
||||
Makefile // Simple gcc Makefile for qhull and libqhullstatic.a
|
||||
Mborland // Makefile for Borland C++ 5.0
|
||||
|
||||
libqhull.h // header file for qhull
|
||||
user.h // header file of user definable constants
|
||||
libqhull.c // Quickhull algorithm with partitioning
|
||||
user.c // user re-definable functions
|
||||
usermem.c
|
||||
userprintf.c
|
||||
userprintf_rbox.c
|
||||
|
||||
qhull_a.h // include files for libqhull/*.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
|
||||
random.c // utilities w/ Park & Miller's random number generator
|
||||
random.h
|
||||
rboxlib.c // point set generator for rbox
|
||||
stat.c // statistics
|
||||
stat.h
|
||||
|
||||
src/libqhull_r
|
||||
libqhull_r.pro // Qt project for rentrant, shared library (qhull_r.dll)
|
||||
index.htm // design documentation for libqhull_r
|
||||
qh-*_r.htm
|
||||
qhull_r-exports.def // Export Definition files for Visual C++
|
||||
qhull_r-nomerge-exports.def
|
||||
Makefile // Simple gcc Makefile for qhull and libqhullstatic.a
|
||||
|
||||
libqhull_r.h // header file for qhull
|
||||
user_r.h // header file of user definable constants
|
||||
libqhull_r.c // Quickhull algorithm wi_r.hpartitioning
|
||||
user_r.c // user re-definable functions
|
||||
usermem.c
|
||||
userprintf.c
|
||||
userprintf_rbox.c
|
||||
qhull_ra.h // include files for libqhull/*_r.c
|
||||
geom_r.c // geometric routines
|
||||
geom2.c
|
||||
geom_r.h
|
||||
global_r.c // global variables
|
||||
io_r.c // input-output routines
|
||||
io_r.h
|
||||
mem_r.c // memory routines, this is stand-alone code
|
||||
mem.h
|
||||
merge_r.c // merging of non-convex facets
|
||||
merge.h
|
||||
poly_r.c // polyhedron routines
|
||||
poly2.c
|
||||
poly_r.h
|
||||
qset_r.c // set routines, this only depends on mem_r.c
|
||||
qset.h
|
||||
random_r.c // utilities w/ Park & Miller's random number generator
|
||||
random.h
|
||||
rboxlib_r.c // point set generator for rbox
|
||||
stat_r.c // statistics
|
||||
stat.h
|
||||
|
||||
src/libqhullcpp/
|
||||
libqhullcpp.pro // Qt project for renentrant, static C++ library
|
||||
Qhull.cpp // Calls libqhull_r.c from C++
|
||||
Qhull.h
|
||||
qt-qhull.cpp // Supporting methods for Qt
|
||||
|
||||
Coordinates.cpp // input classes
|
||||
Coordinates.h
|
||||
|
||||
PointCoordinates.cpp
|
||||
PointCoordinates.h
|
||||
RboxPoints.cpp // call rboxlib.c from C++
|
||||
RboxPoints.h
|
||||
|
||||
QhullFacet.cpp // data structure classes
|
||||
QhullFacet.h
|
||||
QhullHyperplane.cpp
|
||||
QhullHyperplane.h
|
||||
QhullPoint.cpp
|
||||
QhullPoint.h
|
||||
QhullQh.cpp
|
||||
QhullRidge.cpp
|
||||
QhullRidge.h
|
||||
QhullVertex.cpp
|
||||
QhullVertex.h
|
||||
|
||||
QhullFacetList.cpp // collection classes
|
||||
QhullFacetList.h
|
||||
QhullFacetSet.cpp
|
||||
QhullFacetSet.h
|
||||
QhullIterator.h
|
||||
QhullLinkedList.h
|
||||
QhullPoints.cpp
|
||||
QhullPoints.h
|
||||
QhullPointSet.cpp
|
||||
QhullPointSet.h
|
||||
QhullSet.cpp
|
||||
QhullSet.h
|
||||
QhullSets.h
|
||||
QhullVertexSet.cpp
|
||||
QhullVertexSet.h
|
||||
|
||||
functionObjects.h // supporting classes
|
||||
QhullError.cpp
|
||||
QhullError.h
|
||||
QhullQh.cpp
|
||||
QhullQh.h
|
||||
QhullStat.cpp
|
||||
QhullStat.h
|
||||
QhullUser.cpp
|
||||
QhullUser.h
|
||||
RoadError.cpp // Supporting base classes
|
||||
RoadError.h
|
||||
RoadLogEvent.cpp
|
||||
RoadLogEvent.h
|
||||
usermem_r-cpp.cpp // Optional override for qh_exit() to throw an error
|
||||
|
||||
src/libqhullstatic/
|
||||
libqhullstatic.pro // Qt project for non-reentrant, static library
|
||||
|
||||
src/libqhullstatic_r/
|
||||
libqhullstatic_r.pro // Qt project for reentrant, static library
|
||||
|
||||
src/qhulltest/
|
||||
qhulltest.pro // Qt project for test of C++ interface
|
||||
Coordinates_test.cpp // Test of each class
|
||||
PointCoordinates_test.cpp
|
||||
Qhull_test.cpp
|
||||
QhullFacet_test.cpp
|
||||
QhullFacetList_test.cpp
|
||||
QhullFacetSet_test.cpp
|
||||
QhullHyperplane_test.cpp
|
||||
QhullLinkedList_test.cpp
|
||||
QhullPoint_test.cpp
|
||||
QhullPoints_test.cpp
|
||||
QhullPointSet_test.cpp
|
||||
QhullRidge_test.cpp
|
||||
QhullSet_test.cpp
|
||||
QhullVertex_test.cpp
|
||||
QhullVertexSet_test.cpp
|
||||
RboxPoints_test.cpp
|
||||
RoadTest.cpp // Run multiple test files with QTestLib
|
||||
RoadTest.h
|
||||
|
||||
------------------
|
||||
Authors
|
||||
|
||||
C. Bradford Barber Hannu Huhdanpaa (Version 1.0)
|
||||
bradb@shore.net hannu@qhull.org
|
||||
|
||||
Qhull 1.0 and 2.0 were 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.
|
||||
@@ -0,0 +1,69 @@
|
||||
#include <stdlib.h>
|
||||
#include "libqhull_r.h"
|
||||
|
||||
qhT *qh_alloc_qh(FILE *errfile) {
|
||||
qhT *qh = (qhT*) qh_malloc(sizeof(qhT));
|
||||
QHULL_LIB_CHECK
|
||||
if (qh) qh_zero(qh, errfile);
|
||||
return qh;
|
||||
}
|
||||
|
||||
/* Free the qhT pointer.
|
||||
|
||||
Note: qh_freeqhull and qh_memfreeshort should be called before calling qh_free_qh. */
|
||||
void qh_free_qh(qhT *qh) {
|
||||
qh_free(qh);
|
||||
}
|
||||
|
||||
#define GETTER(TYPE, FIELD) TYPE qh_get_##FIELD(const qhT *qh) { return qh->FIELD; }
|
||||
#define SETTER(TYPE, FIELD) void qh_set_##FIELD(qhT *qh, TYPE _val_) { qh->FIELD = _val_; }
|
||||
|
||||
/* required to emulate the various FOR* macros */
|
||||
GETTER(facetT*, facet_list)
|
||||
GETTER(pointT*, first_point)
|
||||
GETTER(int, hull_dim)
|
||||
GETTER(int, num_facets)
|
||||
GETTER(int, num_points)
|
||||
GETTER(int, num_vertices)
|
||||
GETTER(vertexT*, vertex_list)
|
||||
|
||||
/* suggested by @blegat based on Qhull.jl wrappers */
|
||||
GETTER(realT, totarea)
|
||||
GETTER(realT, totvol)
|
||||
GETTER(boolT, hasAreaVolume)
|
||||
SETTER(boolT, hasAreaVolume)
|
||||
GETTER(boolT, hasTriangulation)
|
||||
SETTER(boolT, hasTriangulation)
|
||||
|
||||
/* suggested by @JuhaHeiskala based on his DirectQHull.jl wrapper */
|
||||
GETTER(int, num_good)
|
||||
GETTER(setT*, del_vertices)
|
||||
GETTER(int, input_dim)
|
||||
|
||||
/* other accessors, mimicking those provided by the scipy API: */
|
||||
GETTER(boolT, DELAUNAY)
|
||||
GETTER(boolT, SCALElast)
|
||||
GETTER(boolT, KEEPcoplanar)
|
||||
GETTER(boolT, MERGEexact)
|
||||
GETTER(boolT, NOerrexit)
|
||||
GETTER(boolT, PROJECTdelaunay)
|
||||
GETTER(boolT, ATinfinity)
|
||||
GETTER(boolT, UPPERdelaunay)
|
||||
GETTER(int, normal_size)
|
||||
GETTER(int, num_visible)
|
||||
GETTER(int, center_size)
|
||||
GETTER(const char *, qhull_command)
|
||||
GETTER(facetT*, facet_tail)
|
||||
GETTER(vertexT*, vertex_tail)
|
||||
GETTER(unsigned int, facet_id)
|
||||
GETTER(unsigned int, visit_id)
|
||||
GETTER(unsigned int, vertex_visit)
|
||||
GETTER(pointT*, input_points)
|
||||
GETTER(coordT*, feasible_point)
|
||||
GETTER(realT, last_low)
|
||||
GETTER(realT, last_high)
|
||||
GETTER(realT, last_newhigh)
|
||||
GETTER(realT, max_outside)
|
||||
GETTER(realT, MINoutside)
|
||||
GETTER(realT, DISTround)
|
||||
GETTER(setT*, other_points)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,189 @@
|
||||
/*<html><pre> -<a href="qh-geom_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
geom_r.h
|
||||
header file for geometric routines
|
||||
|
||||
see qh-geom_r.htm and geom_r.c
|
||||
|
||||
Copyright (c) 1993-2020 The Geometry Center.
|
||||
$Id: //main/2019/qhull/src/libqhull_r/geom_r.h#2 $$Change: 2953 $
|
||||
$DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
|
||||
*/
|
||||
|
||||
#ifndef qhDEFgeom
|
||||
#define qhDEFgeom 1
|
||||
|
||||
#include "libqhull_r.h"
|
||||
|
||||
/* ============ -macros- ======================== */
|
||||
|
||||
/*-<a href="qh-geom_r.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_r.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_r.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_r.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_r.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_r.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_r.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_r.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 ======= */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void qh_backnormal(qhT *qh, realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero);
|
||||
void qh_distplane(qhT *qh, pointT *point, facetT *facet, realT *dist);
|
||||
facetT *qh_findbest(qhT *qh, pointT *point, facetT *startfacet,
|
||||
boolT bestoutside, boolT isnewfacets, boolT noupper,
|
||||
realT *dist, boolT *isoutside, int *numpart);
|
||||
facetT *qh_findbesthorizon(qhT *qh, boolT ischeckmax, pointT *point,
|
||||
facetT *startfacet, boolT noupper, realT *bestdist, int *numpart);
|
||||
facetT *qh_findbestnew(qhT *qh, pointT *point, facetT *startfacet, realT *dist,
|
||||
boolT bestoutside, boolT *isoutside, int *numpart);
|
||||
void qh_gausselim(qhT *qh, realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero);
|
||||
realT qh_getangle(qhT *qh, pointT *vect1, pointT *vect2);
|
||||
pointT *qh_getcenter(qhT *qh, setT *vertices);
|
||||
pointT *qh_getcentrum(qhT *qh, facetT *facet);
|
||||
coordT qh_getdistance(qhT *qh, facetT *facet, facetT *neighbor, coordT *mindist, coordT *maxdist);
|
||||
void qh_normalize(qhT *qh, coordT *normal, int dim, boolT toporient);
|
||||
void qh_normalize2(qhT *qh, coordT *normal, int dim, boolT toporient,
|
||||
realT *minnorm, boolT *ismin);
|
||||
pointT *qh_projectpoint(qhT *qh, pointT *point, facetT *facet, realT dist);
|
||||
|
||||
void qh_setfacetplane(qhT *qh, facetT *newfacets);
|
||||
void qh_sethyperplane_det(qhT *qh, int dim, coordT **rows, coordT *point0,
|
||||
boolT toporient, coordT *normal, realT *offset, boolT *nearzero);
|
||||
void qh_sethyperplane_gauss(qhT *qh, int dim, coordT **rows, pointT *point0,
|
||||
boolT toporient, coordT *normal, coordT *offset, boolT *nearzero);
|
||||
boolT qh_sharpnewfacets(qhT *qh);
|
||||
|
||||
/*========= infrequently used code in geom2_r.c =============*/
|
||||
|
||||
coordT *qh_copypoints(qhT *qh, coordT *points, int numpoints, int dimension);
|
||||
void qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]);
|
||||
realT qh_determinant(qhT *qh, realT **rows, int dim, boolT *nearzero);
|
||||
realT qh_detjoggle(qhT *qh, pointT *points, int numpoints, int dimension);
|
||||
void qh_detmaxoutside(qhT *qh);
|
||||
void qh_detroundoff(qhT *qh);
|
||||
realT qh_detsimplex(qhT *qh, pointT *apex, setT *points, int dim, boolT *nearzero);
|
||||
realT qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp);
|
||||
realT qh_distround(qhT *qh, int dimension, realT maxabs, realT maxsumabs);
|
||||
realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv);
|
||||
realT qh_facetarea(qhT *qh, facetT *facet);
|
||||
realT qh_facetarea_simplex(qhT *qh, int dim, coordT *apex, setT *vertices,
|
||||
vertexT *notvertex, boolT toporient, coordT *normal, realT *offset);
|
||||
pointT *qh_facetcenter(qhT *qh, setT *vertices);
|
||||
facetT *qh_findgooddist(qhT *qh, pointT *point, facetT *facetA, realT *distp, facetT **facetlist);
|
||||
vertexT *qh_furthestnewvertex(qhT *qh, unsigned int unvisited, facetT *facet, realT *maxdistp /* qh.newvertex_list */);
|
||||
vertexT *qh_furthestvertex(qhT *qh, facetT *facetA, facetT *facetB, realT *maxdistp, realT *mindistp);
|
||||
void qh_getarea(qhT *qh, facetT *facetlist);
|
||||
boolT qh_gram_schmidt(qhT *qh, int dim, realT **rows);
|
||||
boolT qh_inthresholds(qhT *qh, coordT *normal, realT *angle);
|
||||
void qh_joggleinput(qhT *qh);
|
||||
realT *qh_maxabsval(realT *normal, int dim);
|
||||
setT *qh_maxmin(qhT *qh, pointT *points, int numpoints, int dimension);
|
||||
realT qh_maxouter(qhT *qh);
|
||||
void qh_maxsimplex(qhT *qh, 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(qhT *qh, facetT *facet);
|
||||
void qh_outerinner(qhT *qh, facetT *facet, realT *outerplane, realT *innerplane);
|
||||
coordT qh_pointdist(pointT *point1, pointT *point2, int dim);
|
||||
void qh_printmatrix(qhT *qh, FILE *fp, const char *string, realT **rows, int numrow, int numcol);
|
||||
void qh_printpoints(qhT *qh, FILE *fp, const char *string, setT *points);
|
||||
void qh_projectinput(qhT *qh);
|
||||
void qh_projectpoints(qhT *qh, signed char *project, int n, realT *points,
|
||||
int numpoints, int dim, realT *newpoints, int newdim);
|
||||
void qh_rotateinput(qhT *qh, realT **rows);
|
||||
void qh_rotatepoints(qhT *qh, realT *points, int numpoints, int dim, realT **rows);
|
||||
void qh_scaleinput(qhT *qh);
|
||||
void qh_scalelast(qhT *qh, coordT *points, int numpoints, int dim, coordT low,
|
||||
coordT high, coordT newhigh);
|
||||
void qh_scalepoints(qhT *qh, pointT *points, int numpoints, int dim,
|
||||
realT *newlows, realT *newhighs);
|
||||
boolT qh_sethalfspace(qhT *qh, int dim, coordT *coords, coordT **nextp,
|
||||
coordT *normal, coordT *offset, coordT *feasible);
|
||||
coordT *qh_sethalfspace_all(qhT *qh, int dim, int count, coordT *halfspaces, pointT *feasible);
|
||||
coordT qh_vertex_bestdist(qhT *qh, setT *vertices);
|
||||
coordT qh_vertex_bestdist2(qhT *qh, setT *vertices, vertexT **vertexp, vertexT **vertexp2);
|
||||
pointT *qh_voronoi_center(qhT *qh, int dim, setT *points);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /* qhDEFgeom */
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+4128
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,166 @@
|
||||
/*<html><pre> -<a href="qh-io_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
io_r.h
|
||||
declarations of Input/Output functions
|
||||
|
||||
see README, libqhull_r.h and io_r.c
|
||||
|
||||
Copyright (c) 1993-2020 The Geometry Center.
|
||||
$Id: //main/2019/qhull/src/libqhull_r/io_r.h#3 $$Change: 2953 $
|
||||
$DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
|
||||
*/
|
||||
|
||||
#ifndef qhDEFio
|
||||
#define qhDEFio 1
|
||||
|
||||
#include "libqhull_r.h"
|
||||
|
||||
/*============ constants and flags ==================*/
|
||||
|
||||
/*-<a href="qh-io_r.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_r.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_r.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_r.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_r.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_r.htm#TOC"
|
||||
>--------------------------------</a><a name="printvridgeT">-</a>
|
||||
|
||||
printvridgeT
|
||||
prints results of qh_printvdiagram
|
||||
|
||||
see:
|
||||
<a href="io_r.c#printvridge">qh_printvridge</a> for an example
|
||||
*/
|
||||
typedef void (*printvridgeT)(qhT *qh, FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
|
||||
|
||||
/*============== -prototypes in alphabetical order =========*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void qh_dfacet(qhT *qh, unsigned int id);
|
||||
void qh_dvertex(qhT *qh, unsigned int id);
|
||||
int qh_compare_facetarea(const void *p1, const void *p2);
|
||||
int qh_compare_facetvisit(const void *p1, const void *p2);
|
||||
int qh_compare_nummerge(const void *p1, const void *p2);
|
||||
void qh_copyfilename(qhT *qh, char *filename, int size, const char* source, int length);
|
||||
void qh_countfacets(qhT *qh, facetT *facetlist, setT *facets, boolT printall,
|
||||
int *numfacetsp, int *numsimplicialp, int *totneighborsp,
|
||||
int *numridgesp, int *numcoplanarsp, int *numnumtricoplanarsp);
|
||||
pointT *qh_detvnorm(qhT *qh, vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp);
|
||||
setT *qh_detvridge(qhT *qh, vertexT *vertex);
|
||||
setT *qh_detvridge3(qhT *qh, vertexT *atvertex, vertexT *vertex);
|
||||
int qh_eachvoronoi(qhT *qh, FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder);
|
||||
int qh_eachvoronoi_all(qhT *qh, FILE *fp, printvridgeT printvridge, boolT isUpper, qh_RIDGE innerouter, boolT inorder);
|
||||
void qh_facet2point(qhT *qh, facetT *facet, pointT **point0, pointT **point1, realT *mindist);
|
||||
setT *qh_facetvertices(qhT *qh, facetT *facetlist, setT *facets, boolT allfacets);
|
||||
void qh_geomplanes(qhT *qh, facetT *facet, realT *outerplane, realT *innerplane);
|
||||
void qh_markkeep(qhT *qh, facetT *facetlist);
|
||||
setT *qh_markvoronoi(qhT *qh, facetT *facetlist, setT *facets, boolT printall, boolT *isLowerp, int *numcentersp);
|
||||
void qh_order_vertexneighbors(qhT *qh, vertexT *vertex);
|
||||
void qh_prepare_output(qhT *qh);
|
||||
void qh_printafacet(qhT *qh, FILE *fp, qh_PRINT format, facetT *facet, boolT printall);
|
||||
void qh_printbegin(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
|
||||
void qh_printcenter(qhT *qh, FILE *fp, qh_PRINT format, const char *string, facetT *facet);
|
||||
void qh_printcentrum(qhT *qh, FILE *fp, facetT *facet, realT radius);
|
||||
void qh_printend(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
|
||||
void qh_printend4geom(qhT *qh, FILE *fp, facetT *facet, int *num, boolT printall);
|
||||
void qh_printextremes(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall);
|
||||
void qh_printextremes_2d(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall);
|
||||
void qh_printextremes_d(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall);
|
||||
void qh_printfacet(qhT *qh, FILE *fp, facetT *facet);
|
||||
void qh_printfacet2math(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format, int notfirst);
|
||||
void qh_printfacet2geom(qhT *qh, FILE *fp, facetT *facet, realT color[3]);
|
||||
void qh_printfacet2geom_points(qhT *qh, FILE *fp, pointT *point1, pointT *point2,
|
||||
facetT *facet, realT offset, realT color[3]);
|
||||
void qh_printfacet3math(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format, int notfirst);
|
||||
void qh_printfacet3geom_nonsimplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]);
|
||||
void qh_printfacet3geom_points(qhT *qh, FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]);
|
||||
void qh_printfacet3geom_simplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]);
|
||||
void qh_printfacet3vertex(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format);
|
||||
void qh_printfacet4geom_nonsimplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]);
|
||||
void qh_printfacet4geom_simplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]);
|
||||
void qh_printfacetNvertex_nonsimplicial(qhT *qh, FILE *fp, facetT *facet, int id, qh_PRINT format);
|
||||
void qh_printfacetNvertex_simplicial(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format);
|
||||
void qh_printfacetheader(qhT *qh, FILE *fp, facetT *facet);
|
||||
void qh_printfacetridges(qhT *qh, FILE *fp, facetT *facet);
|
||||
void qh_printfacets(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
|
||||
void qh_printhyperplaneintersection(qhT *qh, FILE *fp, facetT *facet1, facetT *facet2,
|
||||
setT *vertices, realT color[3]);
|
||||
void qh_printline3geom(qhT *qh, FILE *fp, pointT *pointA, pointT *pointB, realT color[3]);
|
||||
void qh_printneighborhood(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall);
|
||||
void qh_printpoint(qhT *qh, FILE *fp, const char *string, pointT *point);
|
||||
void qh_printpointid(qhT *qh, FILE *fp, const char *string, int dim, pointT *point, int id);
|
||||
void qh_printpoint3(qhT *qh, FILE *fp, pointT *point);
|
||||
void qh_printpoints_out(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall);
|
||||
void qh_printpointvect(qhT *qh, FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]);
|
||||
void qh_printpointvect2(qhT *qh, FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius);
|
||||
void qh_printridge(qhT *qh, FILE *fp, ridgeT *ridge);
|
||||
void qh_printspheres(qhT *qh, FILE *fp, setT *vertices, realT radius);
|
||||
void qh_printvdiagram(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
|
||||
int qh_printvdiagram2(qhT *qh, FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder);
|
||||
void qh_printvertex(qhT *qh, FILE *fp, vertexT *vertex);
|
||||
void qh_printvertexlist(qhT *qh, FILE *fp, const char* string, facetT *facetlist,
|
||||
setT *facets, boolT printall);
|
||||
void qh_printvertices(qhT *qh, FILE *fp, const char* string, setT *vertices);
|
||||
void qh_printvneighbors(qhT *qh, FILE *fp, facetT* facetlist, setT *facets, boolT printall);
|
||||
void qh_printvoronoi(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
|
||||
void qh_printvnorm(qhT *qh, FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
|
||||
void qh_printvridge(qhT *qh, FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
|
||||
void qh_produce_output(qhT *qh);
|
||||
void qh_produce_output2(qhT *qh);
|
||||
void qh_projectdim3(qhT *qh, pointT *source, pointT *destination);
|
||||
int qh_readfeasible(qhT *qh, int dim, const char *curline);
|
||||
coordT *qh_readpoints(qhT *qh, int *numpoints, int *dimension, boolT *ismalloc);
|
||||
void qh_setfeasible(qhT *qh, int dim);
|
||||
boolT qh_skipfacet(qhT *qh, facetT *facet);
|
||||
char *qh_skipfilename(qhT *qh, char *filename);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* qhDEFio */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,566 @@
|
||||
/*<html><pre> -<a href="qh-mem_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
mem_r.c
|
||||
memory management routines for qhull
|
||||
|
||||
See libqhull/mem.c for a standalone program.
|
||||
|
||||
To initialize memory:
|
||||
|
||||
qh_meminit(qh, stderr);
|
||||
qh_meminitbuffers(qh, qh->IStracing, qh_MEMalign, 7, qh_MEMbufsize,qh_MEMinitbuf);
|
||||
qh_memsize(qh, (int)sizeof(facetT));
|
||||
qh_memsize(qh, (int)sizeof(facetT));
|
||||
...
|
||||
qh_memsetup(qh);
|
||||
|
||||
To free up all memory buffers:
|
||||
qh_memfreeshort(qh, &curlong, &totlong);
|
||||
|
||||
if qh_NOmem,
|
||||
malloc/free is used instead of mem_r.c
|
||||
|
||||
notes:
|
||||
uses Quickfit algorithm (freelists for commonly allocated sizes)
|
||||
assumes small sizes for freelists (it discards the tail of memory buffers)
|
||||
|
||||
see:
|
||||
qh-mem_r.htm and mem_r.h
|
||||
global_r.c (qh_initbuffers) for an example of using mem_r.c
|
||||
|
||||
Copyright (c) 1993-2020 The Geometry Center.
|
||||
$Id: //main/2019/qhull/src/libqhull_r/mem_r.c#7 $$Change: 2953 $
|
||||
$DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
|
||||
*/
|
||||
|
||||
#include "libqhull_r.h" /* includes user_r.h and mem_r.h */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef qh_NOmem
|
||||
|
||||
/*============= internal functions ==============*/
|
||||
|
||||
static int qh_intcompare(const void *i, const void *j);
|
||||
|
||||
/*========== functions in alphabetical order ======== */
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>-------------------------------</a><a name="intcompare">-</a>
|
||||
|
||||
qh_intcompare( i, j )
|
||||
used by qsort and bsearch to compare two integers
|
||||
*/
|
||||
static int qh_intcompare(const void *i, const void *j) {
|
||||
return(*((const int *)i) - *((const int *)j));
|
||||
} /* intcompare */
|
||||
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>--------------------------------</a><a name="memalloc">-</a>
|
||||
|
||||
qh_memalloc(qh, insize )
|
||||
returns object of insize bytes
|
||||
qhmem is the global memory structure
|
||||
|
||||
returns:
|
||||
pointer to allocated memory
|
||||
errors if insufficient memory
|
||||
|
||||
notes:
|
||||
use explicit type conversion to avoid type warnings on some compilers
|
||||
actual object may be larger than insize
|
||||
use qh_memalloc_() for inline code for quick allocations
|
||||
logs allocations if 'T5'
|
||||
caller is responsible for freeing the memory.
|
||||
short memory is freed on shutdown by qh_memfreeshort unless qh_NOmem
|
||||
|
||||
design:
|
||||
if size < qh->qhmem.LASTsize
|
||||
if qh->qhmem.freelists[size] non-empty
|
||||
return first object on freelist
|
||||
else
|
||||
round up request to size of qh->qhmem.freelists[size]
|
||||
allocate new allocation buffer if necessary
|
||||
allocate object from allocation buffer
|
||||
else
|
||||
allocate object with qh_malloc() in user_r.c
|
||||
*/
|
||||
void *qh_memalloc(qhT *qh, int insize) {
|
||||
void **freelistp, *newbuffer;
|
||||
int idx, size, n;
|
||||
int outsize, bufsize;
|
||||
void *object;
|
||||
|
||||
if (insize<0) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6235, "qhull error (qh_memalloc): negative request size (%d). Did int overflow due to high-D?\n", insize); /* WARN64 */
|
||||
qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
|
||||
}
|
||||
if (insize>=0 && insize <= qh->qhmem.LASTsize) {
|
||||
idx= qh->qhmem.indextable[insize];
|
||||
outsize= qh->qhmem.sizetable[idx];
|
||||
qh->qhmem.totshort += outsize;
|
||||
freelistp= qh->qhmem.freelists+idx;
|
||||
if ((object= *freelistp)) {
|
||||
qh->qhmem.cntquick++;
|
||||
qh->qhmem.totfree -= outsize;
|
||||
*freelistp= *((void **)*freelistp); /* replace freelist with next object */
|
||||
#ifdef qh_TRACEshort
|
||||
n= qh->qhmem.cntshort+qh->qhmem.cntquick+qh->qhmem.freeshort;
|
||||
if (qh->qhmem.IStracing >= 5)
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 8141, "qh_mem %p n %8d alloc quick: %d bytes (tot %d cnt %d)\n", object, n, outsize, qh->qhmem.totshort, qh->qhmem.cntshort+qh->qhmem.cntquick-qh->qhmem.freeshort);
|
||||
#endif
|
||||
return(object);
|
||||
}else {
|
||||
qh->qhmem.cntshort++;
|
||||
if (outsize > qh->qhmem.freesize) {
|
||||
qh->qhmem.totdropped += qh->qhmem.freesize;
|
||||
if (!qh->qhmem.curbuffer)
|
||||
bufsize= qh->qhmem.BUFinit;
|
||||
else
|
||||
bufsize= qh->qhmem.BUFsize;
|
||||
if (!(newbuffer= qh_malloc((size_t)bufsize))) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6080, "qhull error (qh_memalloc): insufficient memory to allocate short memory buffer (%d bytes)\n", bufsize);
|
||||
qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
|
||||
}
|
||||
*((void **)newbuffer)= qh->qhmem.curbuffer; /* prepend newbuffer to curbuffer
|
||||
list. newbuffer!=0 by QH6080 */
|
||||
qh->qhmem.curbuffer= newbuffer;
|
||||
size= ((int)sizeof(void **) + qh->qhmem.ALIGNmask) & ~qh->qhmem.ALIGNmask;
|
||||
qh->qhmem.freemem= (void *)((char *)newbuffer+size);
|
||||
qh->qhmem.freesize= bufsize - size;
|
||||
qh->qhmem.totbuffer += bufsize - size; /* easier to check */
|
||||
/* Periodically test totbuffer. It matches at beginning and exit of every call */
|
||||
n= qh->qhmem.totshort + qh->qhmem.totfree + qh->qhmem.totdropped + qh->qhmem.freesize - outsize;
|
||||
if (qh->qhmem.totbuffer != n) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6212, "qhull internal error (qh_memalloc): short totbuffer %d != totshort+totfree... %d\n", qh->qhmem.totbuffer, n);
|
||||
qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
|
||||
}
|
||||
}
|
||||
object= qh->qhmem.freemem;
|
||||
qh->qhmem.freemem= (void *)((char *)qh->qhmem.freemem + outsize);
|
||||
qh->qhmem.freesize -= outsize;
|
||||
qh->qhmem.totunused += outsize - insize;
|
||||
#ifdef qh_TRACEshort
|
||||
n= qh->qhmem.cntshort+qh->qhmem.cntquick+qh->qhmem.freeshort;
|
||||
if (qh->qhmem.IStracing >= 5)
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 8140, "qh_mem %p n %8d alloc short: %d bytes (tot %d cnt %d)\n", object, n, outsize, qh->qhmem.totshort, qh->qhmem.cntshort+qh->qhmem.cntquick-qh->qhmem.freeshort);
|
||||
#endif
|
||||
return object;
|
||||
}
|
||||
}else { /* long allocation */
|
||||
if (!qh->qhmem.indextable) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6081, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n");
|
||||
qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
|
||||
}
|
||||
outsize= insize;
|
||||
qh->qhmem.cntlong++;
|
||||
qh->qhmem.totlong += outsize;
|
||||
if (qh->qhmem.maxlong < qh->qhmem.totlong)
|
||||
qh->qhmem.maxlong= qh->qhmem.totlong;
|
||||
if (!(object= qh_malloc((size_t)outsize))) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6082, "qhull error (qh_memalloc): insufficient memory to allocate %d bytes\n", outsize);
|
||||
qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
|
||||
}
|
||||
if (qh->qhmem.IStracing >= 5)
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 8057, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qh->qhmem.cntlong+qh->qhmem.freelong, outsize, qh->qhmem.totlong, qh->qhmem.cntlong-qh->qhmem.freelong);
|
||||
}
|
||||
return(object);
|
||||
} /* memalloc */
|
||||
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>--------------------------------</a><a name="memcheck">-</a>
|
||||
|
||||
qh_memcheck(qh)
|
||||
*/
|
||||
void qh_memcheck(qhT *qh) {
|
||||
int i, count, totfree= 0;
|
||||
void *object;
|
||||
|
||||
if (!qh) {
|
||||
qh_fprintf_stderr(6243, "qhull internal error (qh_memcheck): qh is 0. It does not point to a qhT\n");
|
||||
qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */
|
||||
}
|
||||
if (qh->qhmem.ferr == 0 || qh->qhmem.IStracing < 0 || qh->qhmem.IStracing > 10 || (((qh->qhmem.ALIGNmask+1) & qh->qhmem.ALIGNmask) != 0)) {
|
||||
qh_fprintf_stderr(6244, "qhull internal error (qh_memcheck): either qh->qhmem is overwritten or qh->qhmem is not initialized. Call qh_meminit or qh_new_qhull before calling qh_mem routines. ferr %p, IsTracing %d, ALIGNmask 0x%x\n",
|
||||
(void *) qh->qhmem.ferr, qh->qhmem.IStracing, qh->qhmem.ALIGNmask);
|
||||
qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */
|
||||
}
|
||||
if (qh->qhmem.IStracing != 0)
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 8143, "qh_memcheck: check size of freelists on qh->qhmem\nqh_memcheck: A segmentation fault indicates an overwrite of qh->qhmem\n");
|
||||
for (i=0; i < qh->qhmem.TABLEsize; i++) {
|
||||
count=0;
|
||||
for (object= qh->qhmem.freelists[i]; object; object= *((void **)object))
|
||||
count++;
|
||||
totfree += qh->qhmem.sizetable[i] * count;
|
||||
}
|
||||
if (totfree != qh->qhmem.totfree) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6211, "qhull internal error (qh_memcheck): totfree %d not equal to freelist total %d\n", qh->qhmem.totfree, totfree);
|
||||
qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
|
||||
}
|
||||
if (qh->qhmem.IStracing != 0)
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 8144, "qh_memcheck: total size of freelists totfree (%d) is the same as qh->qhmem.totfree\n", totfree);
|
||||
} /* memcheck */
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>--------------------------------</a><a name="memfree">-</a>
|
||||
|
||||
qh_memfree(qh, object, insize )
|
||||
free up an object of size bytes
|
||||
size is insize from qh_memalloc
|
||||
|
||||
notes:
|
||||
object may be NULL
|
||||
type checking warns if using (void **)object
|
||||
use qh_memfree_() for quick free's of small objects
|
||||
|
||||
design:
|
||||
if size <= qh->qhmem.LASTsize
|
||||
append object to corresponding freelist
|
||||
else
|
||||
call qh_free(object)
|
||||
*/
|
||||
void qh_memfree(qhT *qh, void *object, int insize) {
|
||||
void **freelistp;
|
||||
int idx, outsize;
|
||||
|
||||
if (!object)
|
||||
return;
|
||||
if (insize <= qh->qhmem.LASTsize) {
|
||||
qh->qhmem.freeshort++;
|
||||
idx= qh->qhmem.indextable[insize];
|
||||
outsize= qh->qhmem.sizetable[idx];
|
||||
qh->qhmem.totfree += outsize;
|
||||
qh->qhmem.totshort -= outsize;
|
||||
freelistp= qh->qhmem.freelists + idx;
|
||||
*((void **)object)= *freelistp;
|
||||
*freelistp= object;
|
||||
#ifdef qh_TRACEshort
|
||||
idx= qh->qhmem.cntshort+qh->qhmem.cntquick+qh->qhmem.freeshort;
|
||||
if (qh->qhmem.IStracing >= 5)
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 8142, "qh_mem %p n %8d free short: %d bytes (tot %d cnt %d)\n", object, idx, outsize, qh->qhmem.totshort, qh->qhmem.cntshort+qh->qhmem.cntquick-qh->qhmem.freeshort);
|
||||
#endif
|
||||
}else {
|
||||
qh->qhmem.freelong++;
|
||||
qh->qhmem.totlong -= insize;
|
||||
if (qh->qhmem.IStracing >= 5)
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 8058, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qh->qhmem.cntlong+qh->qhmem.freelong, insize, qh->qhmem.totlong, qh->qhmem.cntlong-qh->qhmem.freelong);
|
||||
qh_free(object);
|
||||
}
|
||||
} /* memfree */
|
||||
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>-------------------------------</a><a name="memfreeshort">-</a>
|
||||
|
||||
qh_memfreeshort(qh, curlong, totlong )
|
||||
frees up all short and qhmem memory allocations
|
||||
|
||||
returns:
|
||||
number and size of current long allocations
|
||||
|
||||
notes:
|
||||
if qh_NOmem (qh_malloc() for all allocations),
|
||||
short objects (e.g., facetT) are not recovered.
|
||||
use qh_freeqhull(qh, qh_ALL) instead.
|
||||
|
||||
see:
|
||||
qh_freeqhull(qh, allMem)
|
||||
qh_memtotal(qh, curlong, totlong, curshort, totshort, maxlong, totbuffer);
|
||||
*/
|
||||
void qh_memfreeshort(qhT *qh, int *curlong, int *totlong) {
|
||||
void *buffer, *nextbuffer;
|
||||
FILE *ferr;
|
||||
|
||||
*curlong= qh->qhmem.cntlong - qh->qhmem.freelong;
|
||||
*totlong= qh->qhmem.totlong;
|
||||
for (buffer=qh->qhmem.curbuffer; buffer; buffer= nextbuffer) {
|
||||
nextbuffer= *((void **) buffer);
|
||||
qh_free(buffer);
|
||||
}
|
||||
qh->qhmem.curbuffer= NULL;
|
||||
if (qh->qhmem.LASTsize) {
|
||||
qh_free(qh->qhmem.indextable);
|
||||
qh_free(qh->qhmem.freelists);
|
||||
qh_free(qh->qhmem.sizetable);
|
||||
}
|
||||
ferr= qh->qhmem.ferr;
|
||||
memset((char *)&qh->qhmem, 0, sizeof(qh->qhmem)); /* every field is 0, FALSE, NULL */
|
||||
qh->qhmem.ferr= ferr;
|
||||
} /* memfreeshort */
|
||||
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>--------------------------------</a><a name="meminit">-</a>
|
||||
|
||||
qh_meminit(qh, ferr )
|
||||
initialize qhmem and test sizeof(void *)
|
||||
Does not throw errors. qh_exit on failure
|
||||
*/
|
||||
void qh_meminit(qhT *qh, FILE *ferr) {
|
||||
|
||||
memset((char *)&qh->qhmem, 0, sizeof(qh->qhmem)); /* every field is 0, FALSE, NULL */
|
||||
if (ferr)
|
||||
qh->qhmem.ferr= ferr;
|
||||
else
|
||||
qh->qhmem.ferr= stderr;
|
||||
if (sizeof(void *) < sizeof(int)) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6083, "qhull internal error (qh_meminit): sizeof(void *) %d < sizeof(int) %d. qset_r.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
|
||||
qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */
|
||||
}
|
||||
if (sizeof(void *) > sizeof(ptr_intT)) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6084, "qhull internal error (qh_meminit): sizeof(void *) %d > sizeof(ptr_intT) %d. Change ptr_intT in mem_r.h to 'long long'\n", (int)sizeof(void*), (int)sizeof(ptr_intT));
|
||||
qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */
|
||||
}
|
||||
qh_memcheck(qh);
|
||||
} /* meminit */
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>-------------------------------</a><a name="meminitbuffers">-</a>
|
||||
|
||||
qh_meminitbuffers(qh, tracelevel, alignment, numsizes, bufsize, bufinit )
|
||||
initialize qhmem
|
||||
if tracelevel >= 5, trace memory allocations
|
||||
alignment= desired address alignment for memory allocations
|
||||
numsizes= number of freelists
|
||||
bufsize= size of additional memory buffers for short allocations
|
||||
bufinit= size of initial memory buffer for short allocations
|
||||
*/
|
||||
void qh_meminitbuffers(qhT *qh, int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
|
||||
|
||||
qh->qhmem.IStracing= tracelevel;
|
||||
qh->qhmem.NUMsizes= numsizes;
|
||||
qh->qhmem.BUFsize= bufsize;
|
||||
qh->qhmem.BUFinit= bufinit;
|
||||
qh->qhmem.ALIGNmask= alignment-1;
|
||||
if (qh->qhmem.ALIGNmask & ~qh->qhmem.ALIGNmask) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6085, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment);
|
||||
qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
|
||||
}
|
||||
qh->qhmem.sizetable= (int *) calloc((size_t)numsizes, sizeof(int));
|
||||
qh->qhmem.freelists= (void **) calloc((size_t)numsizes, sizeof(void *));
|
||||
if (!qh->qhmem.sizetable || !qh->qhmem.freelists) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6086, "qhull error (qh_meminit): insufficient memory\n");
|
||||
qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
|
||||
}
|
||||
if (qh->qhmem.IStracing >= 1)
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 8059, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
|
||||
} /* meminitbuffers */
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>-------------------------------</a><a name="memsetup">-</a>
|
||||
|
||||
qh_memsetup(qh)
|
||||
set up memory after running memsize()
|
||||
*/
|
||||
void qh_memsetup(qhT *qh) {
|
||||
int k,i;
|
||||
|
||||
qsort(qh->qhmem.sizetable, (size_t)qh->qhmem.TABLEsize, sizeof(int), qh_intcompare);
|
||||
qh->qhmem.LASTsize= qh->qhmem.sizetable[qh->qhmem.TABLEsize-1];
|
||||
if (qh->qhmem.LASTsize >= qh->qhmem.BUFsize || qh->qhmem.LASTsize >= qh->qhmem.BUFinit) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6087, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n",
|
||||
qh->qhmem.LASTsize, qh->qhmem.BUFsize, qh->qhmem.BUFinit);
|
||||
qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
|
||||
}
|
||||
if (!(qh->qhmem.indextable= (int *)qh_malloc((size_t)(qh->qhmem.LASTsize+1) * sizeof(int)))) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6088, "qhull error (qh_memsetup): insufficient memory\n");
|
||||
qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
|
||||
}
|
||||
for (k=qh->qhmem.LASTsize+1; k--; )
|
||||
qh->qhmem.indextable[k]= k;
|
||||
i= 0;
|
||||
for (k=0; k <= qh->qhmem.LASTsize; k++) {
|
||||
if (qh->qhmem.indextable[k] <= qh->qhmem.sizetable[i])
|
||||
qh->qhmem.indextable[k]= i;
|
||||
else
|
||||
qh->qhmem.indextable[k]= ++i;
|
||||
}
|
||||
} /* memsetup */
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>-------------------------------</a><a name="memsize">-</a>
|
||||
|
||||
qh_memsize(qh, size )
|
||||
define a free list for this size
|
||||
*/
|
||||
void qh_memsize(qhT *qh, int size) {
|
||||
int k;
|
||||
|
||||
if (qh->qhmem.LASTsize) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6089, "qhull internal error (qh_memsize): qh_memsize called after qh_memsetup\n");
|
||||
qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
|
||||
}
|
||||
size= (size + qh->qhmem.ALIGNmask) & ~qh->qhmem.ALIGNmask;
|
||||
if (qh->qhmem.IStracing >= 3)
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 3078, "qh_memsize: quick memory of %d bytes\n", size);
|
||||
for (k=qh->qhmem.TABLEsize; k--; ) {
|
||||
if (qh->qhmem.sizetable[k] == size)
|
||||
return;
|
||||
}
|
||||
if (qh->qhmem.TABLEsize < qh->qhmem.NUMsizes)
|
||||
qh->qhmem.sizetable[qh->qhmem.TABLEsize++]= size;
|
||||
else
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 7060, "qhull warning (qh_memsize): free list table has room for only %d sizes\n", qh->qhmem.NUMsizes);
|
||||
} /* memsize */
|
||||
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>-------------------------------</a><a name="memstatistics">-</a>
|
||||
|
||||
qh_memstatistics(qh, fp )
|
||||
print out memory statistics
|
||||
|
||||
Verifies that qh->qhmem.totfree == sum of freelists
|
||||
*/
|
||||
void qh_memstatistics(qhT *qh, FILE *fp) {
|
||||
int i;
|
||||
int count;
|
||||
void *object;
|
||||
|
||||
qh_memcheck(qh);
|
||||
qh_fprintf(qh, fp, 9278, "\nmemory statistics:\n\
|
||||
%7d quick allocations\n\
|
||||
%7d short allocations\n\
|
||||
%7d long allocations\n\
|
||||
%7d short frees\n\
|
||||
%7d long frees\n\
|
||||
%7d bytes of short memory in use\n\
|
||||
%7d bytes of short memory in freelists\n\
|
||||
%7d bytes of dropped short memory\n\
|
||||
%7d bytes of unused short memory (estimated)\n\
|
||||
%7d bytes of long memory allocated (max, except for input)\n\
|
||||
%7d bytes of long memory in use (in %d pieces)\n\
|
||||
%7d bytes of short memory buffers (minus links)\n\
|
||||
%7d bytes per short memory buffer (initially %d bytes)\n",
|
||||
qh->qhmem.cntquick, qh->qhmem.cntshort, qh->qhmem.cntlong,
|
||||
qh->qhmem.freeshort, qh->qhmem.freelong,
|
||||
qh->qhmem.totshort, qh->qhmem.totfree,
|
||||
qh->qhmem.totdropped + qh->qhmem.freesize, qh->qhmem.totunused,
|
||||
qh->qhmem.maxlong, qh->qhmem.totlong, qh->qhmem.cntlong - qh->qhmem.freelong,
|
||||
qh->qhmem.totbuffer, qh->qhmem.BUFsize, qh->qhmem.BUFinit);
|
||||
if (qh->qhmem.cntlarger) {
|
||||
qh_fprintf(qh, fp, 9279, "%7d calls to qh_setlarger\n%7.2g average copy size\n",
|
||||
qh->qhmem.cntlarger, ((double)qh->qhmem.totlarger)/(double)qh->qhmem.cntlarger);
|
||||
qh_fprintf(qh, fp, 9280, " freelists(bytes->count):");
|
||||
}
|
||||
for (i=0; i < qh->qhmem.TABLEsize; i++) {
|
||||
count=0;
|
||||
for (object= qh->qhmem.freelists[i]; object; object= *((void **)object))
|
||||
count++;
|
||||
qh_fprintf(qh, fp, 9281, " %d->%d", qh->qhmem.sizetable[i], count);
|
||||
}
|
||||
qh_fprintf(qh, fp, 9282, "\n\n");
|
||||
} /* memstatistics */
|
||||
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>-------------------------------</a><a name="NOmem">-</a>
|
||||
|
||||
qh_NOmem
|
||||
turn off quick-fit memory allocation
|
||||
|
||||
notes:
|
||||
uses qh_malloc() and qh_free() instead
|
||||
*/
|
||||
#else /* qh_NOmem */
|
||||
|
||||
void *qh_memalloc(qhT *qh, int insize) {
|
||||
void *object;
|
||||
|
||||
if (!(object= qh_malloc((size_t)insize))) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6090, "qhull error (qh_memalloc): insufficient memory\n");
|
||||
qh_errexit(qh, qhmem_ERRmem, NULL, NULL);
|
||||
}
|
||||
qh->qhmem.cntlong++;
|
||||
qh->qhmem.totlong += insize;
|
||||
if (qh->qhmem.maxlong < qh->qhmem.totlong)
|
||||
qh->qhmem.maxlong= qh->qhmem.totlong;
|
||||
if (qh->qhmem.IStracing >= 5)
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 8060, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qh->qhmem.cntlong+qh->qhmem.freelong, insize, qh->qhmem.totlong, qh->qhmem.cntlong-qh->qhmem.freelong);
|
||||
return object;
|
||||
}
|
||||
|
||||
void qh_memcheck(qhT *qh) {
|
||||
}
|
||||
|
||||
void qh_memfree(qhT *qh, void *object, int insize) {
|
||||
|
||||
if (!object)
|
||||
return;
|
||||
qh_free(object);
|
||||
qh->qhmem.freelong++;
|
||||
qh->qhmem.totlong -= insize;
|
||||
if (qh->qhmem.IStracing >= 5)
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 8061, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qh->qhmem.cntlong+qh->qhmem.freelong, insize, qh->qhmem.totlong, qh->qhmem.cntlong-qh->qhmem.freelong);
|
||||
}
|
||||
|
||||
void qh_memfreeshort(qhT *qh, int *curlong, int *totlong) {
|
||||
*totlong= qh->qhmem.totlong;
|
||||
*curlong= qh->qhmem.cntlong - qh->qhmem.freelong;
|
||||
memset((char *)&qh->qhmem, 0, sizeof(qh->qhmem)); /* every field is 0, FALSE, NULL */
|
||||
}
|
||||
|
||||
void qh_meminit(qhT *qh, FILE *ferr) {
|
||||
|
||||
memset((char *)&qh->qhmem, 0, sizeof(qh->qhmem)); /* every field is 0, FALSE, NULL */
|
||||
if (ferr)
|
||||
qh->qhmem.ferr= ferr;
|
||||
else
|
||||
qh->qhmem.ferr= stderr;
|
||||
if (sizeof(void *) < sizeof(int)) {
|
||||
qh_fprintf(qh, qh->qhmem.ferr, 6091, "qhull internal error (qh_meminit): sizeof(void *) %d < sizeof(int) %d. qset_r.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
|
||||
qh_errexit(qh, qhmem_ERRqhull, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void qh_meminitbuffers(qhT *qh, int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
|
||||
|
||||
qh->qhmem.IStracing= tracelevel;
|
||||
}
|
||||
|
||||
void qh_memsetup(qhT *qh) {
|
||||
}
|
||||
|
||||
void qh_memsize(qhT *qh, int size) {
|
||||
}
|
||||
|
||||
void qh_memstatistics(qhT *qh, FILE *fp) {
|
||||
|
||||
qh_fprintf(qh, fp, 9409, "\nmemory statistics:\n\
|
||||
%7d long allocations\n\
|
||||
%7d long frees\n\
|
||||
%7d bytes of long memory allocated (max, except for input)\n\
|
||||
%7d bytes of long memory in use (in %d pieces)\n",
|
||||
qh->qhmem.cntlong,
|
||||
qh->qhmem.freelong,
|
||||
qh->qhmem.maxlong, qh->qhmem.totlong, qh->qhmem.cntlong - qh->qhmem.freelong);
|
||||
}
|
||||
|
||||
#endif /* qh_NOmem */
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>-------------------------------</a><a name="memtotlong">-</a>
|
||||
|
||||
qh_memtotal(qh, totlong, curlong, totshort, curshort, maxlong, totbuffer )
|
||||
Return the total, allocated long and short memory
|
||||
|
||||
returns:
|
||||
Returns the total current bytes of long and short allocations
|
||||
Returns the current count of long and short allocations
|
||||
Returns the maximum long memory and total short buffer (minus one link per buffer)
|
||||
Does not error (for deprecated UsingLibQhull.cpp in libqhullpcpp)
|
||||
*/
|
||||
void qh_memtotal(qhT *qh, int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer) {
|
||||
*totlong= qh->qhmem.totlong;
|
||||
*curlong= qh->qhmem.cntlong - qh->qhmem.freelong;
|
||||
*totshort= qh->qhmem.totshort;
|
||||
*curshort= qh->qhmem.cntshort + qh->qhmem.cntquick - qh->qhmem.freeshort;
|
||||
*maxlong= qh->qhmem.maxlong;
|
||||
*totbuffer= qh->qhmem.totbuffer;
|
||||
} /* memtotlong */
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/*<html><pre> -<a href="qh-mem_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
mem_r.h
|
||||
prototypes for memory management functions
|
||||
|
||||
see qh-mem_r.htm, mem_r.c and qset_r.h
|
||||
|
||||
for error handling, writes message and calls
|
||||
qh_errexit(qhT *qh, qhmem_ERRmem, NULL, NULL) if insufficient memory
|
||||
and
|
||||
qh_errexit(qhT *qh, qhmem_ERRqhull, NULL, NULL) otherwise
|
||||
|
||||
Copyright (c) 1993-2020 The Geometry Center.
|
||||
$Id: //main/2019/qhull/src/libqhull_r/mem_r.h#6 $$Change: 2953 $
|
||||
$DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
|
||||
*/
|
||||
|
||||
#ifndef qhDEFmem
|
||||
#define qhDEFmem 1
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef DEFsetT
|
||||
#define DEFsetT 1
|
||||
typedef struct setT setT; /* defined in qset_r.h */
|
||||
#endif
|
||||
|
||||
#ifndef DEFqhT
|
||||
#define DEFqhT 1
|
||||
typedef struct qhT qhT; /* defined in libqhull_r.h */
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>-------------------------------</a><a name="NOmem">-</a>
|
||||
|
||||
qh_NOmem
|
||||
turn off quick-fit memory allocation
|
||||
|
||||
notes:
|
||||
mem_r.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@qhull.org. If this can
|
||||
not be done, define qh_NOmem to use malloc/free instead.
|
||||
|
||||
#define qh_NOmem
|
||||
*/
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>-------------------------------</a><a name="TRACEshort">-</a>
|
||||
|
||||
qh_TRACEshort
|
||||
Trace short and quick memory allocations at T5
|
||||
|
||||
*/
|
||||
#define qh_TRACEshort
|
||||
|
||||
/*-------------------------------------------
|
||||
to avoid bus errors, memory allocation must consider alignment requirements.
|
||||
malloc() automatically takes care of alignment. Since mem_r.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_r.h#MEMalign">qh_MEMalign</a> in user_r.h for qhull's alignment
|
||||
*/
|
||||
|
||||
#define qhmem_ERRmem 4 /* matches qh_ERRmem in libqhull_r.h */
|
||||
#define qhmem_ERRqhull 5 /* matches qh_ERRqhull in libqhull_r.h */
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>--------------------------------</a><a name="ptr_intT">-</a>
|
||||
|
||||
ptr_intT
|
||||
for casting a void * to an integer-type that holds a pointer
|
||||
Used for integer expressions (e.g., computing qh_gethash() in poly_r.c)
|
||||
|
||||
notes:
|
||||
WARN64 -- these notes indicate 64-bit issues
|
||||
On 64-bit machines, a pointer may be larger than an 'int'.
|
||||
qh_meminit()/mem_r.c checks that 'ptr_intT' holds a 'void*'
|
||||
ptr_intT is typically a signed value, but not necessarily so
|
||||
size_t is typically unsigned, but should match the parameter type
|
||||
Qhull uses int instead of size_t except for system calls such as malloc, qsort, qh_malloc, etc.
|
||||
This matches Qt convention and is easier to work with.
|
||||
*/
|
||||
#if (defined(__MINGW64__)) && defined(_WIN64)
|
||||
typedef long long ptr_intT;
|
||||
#elif defined(_MSC_VER) && defined(_WIN64)
|
||||
typedef long long ptr_intT;
|
||||
#else
|
||||
typedef long ptr_intT;
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>--------------------------------</a><a name="qhmemT">-</a>
|
||||
|
||||
qhmemT
|
||||
global memory structure for mem_r.c
|
||||
|
||||
notes:
|
||||
users should ignore qhmem except for writing extensions
|
||||
qhmem is allocated in mem_r.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 qh->qhmem.
|
||||
*/
|
||||
typedef struct qhmemT qhmemT;
|
||||
|
||||
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 freemem in bytes */
|
||||
setT *tempstack; /* stack of temporary memory, managed by users */
|
||||
FILE *ferr; /* file for reporting errors when 'qh' may be undefined */
|
||||
int IStracing; /* =5 if tracing memory allocations */
|
||||
int cntquick; /* count of quick allocations */
|
||||
/* Note: removing statistics doesn't effect speed */
|
||||
int cntshort; /* count of short allocations */
|
||||
int cntlong; /* count of long allocations */
|
||||
int freeshort; /* count of short memfrees */
|
||||
int freelong; /* count of long memfrees */
|
||||
int totbuffer; /* total short memory buffers minus buffer links */
|
||||
int totdropped; /* total dropped memory at end of short memory buffers (e.g., freesize) */
|
||||
int totfree; /* total size of free, short memory on freelists */
|
||||
int totlong; /* total size of long memory in use */
|
||||
int maxlong; /* maximum totlong */
|
||||
int totshort; /* total size of short memory in use */
|
||||
int totunused; /* total unused short memory (estimated, short size - request size of first allocations) */
|
||||
int cntlarger; /* count of setlarger's */
|
||||
int totlarger; /* total copied by setlarger */
|
||||
};
|
||||
|
||||
|
||||
/*==================== -macros ====================*/
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>--------------------------------</a><a name="memalloc_">-</a>
|
||||
|
||||
qh_memalloc_(qh, insize, freelistp, object, type)
|
||||
returns object of size bytes
|
||||
assumes size<=qh->qhmem.LASTsize and void **freelistp is a temp
|
||||
*/
|
||||
|
||||
#if defined qh_NOmem
|
||||
#define qh_memalloc_(qh, insize, freelistp, object, type) {\
|
||||
(void)freelistp; /* Avoid warnings */ \
|
||||
object= (type *)qh_memalloc(qh, insize); }
|
||||
#elif defined qh_TRACEshort
|
||||
#define qh_memalloc_(qh, insize, freelistp, object, type) {\
|
||||
(void)freelistp; /* Avoid warnings */ \
|
||||
object= (type *)qh_memalloc(qh, insize); }
|
||||
#else /* !qh_NOmem */
|
||||
|
||||
#define qh_memalloc_(qh, insize, freelistp, object, type) {\
|
||||
freelistp= qh->qhmem.freelists + qh->qhmem.indextable[insize];\
|
||||
if ((object= (type *)*freelistp)) {\
|
||||
qh->qhmem.totshort += qh->qhmem.sizetable[qh->qhmem.indextable[insize]]; \
|
||||
qh->qhmem.totfree -= qh->qhmem.sizetable[qh->qhmem.indextable[insize]]; \
|
||||
qh->qhmem.cntquick++; \
|
||||
*freelistp= *((void **)*freelistp);\
|
||||
}else object= (type *)qh_memalloc(qh, insize);}
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-mem_r.htm#TOC"
|
||||
>--------------------------------</a><a name="memfree_">-</a>
|
||||
|
||||
qh_memfree_(qh, object, insize, freelistp)
|
||||
free up an object
|
||||
|
||||
notes:
|
||||
object may be NULL
|
||||
assumes size<=qh->qhmem.LASTsize and void **freelistp is a temp
|
||||
*/
|
||||
#if defined qh_NOmem
|
||||
#define qh_memfree_(qh, object, insize, freelistp) {\
|
||||
(void)freelistp; /* Avoid warnings */ \
|
||||
qh_memfree(qh, object, insize); }
|
||||
#elif defined qh_TRACEshort
|
||||
#define qh_memfree_(qh, object, insize, freelistp) {\
|
||||
(void)freelistp; /* Avoid warnings */ \
|
||||
qh_memfree(qh, object, insize); }
|
||||
#else /* !qh_NOmem */
|
||||
|
||||
#define qh_memfree_(qh, object, insize, freelistp) {\
|
||||
if (object) { \
|
||||
qh->qhmem.freeshort++;\
|
||||
freelistp= qh->qhmem.freelists + qh->qhmem.indextable[insize];\
|
||||
qh->qhmem.totshort -= qh->qhmem.sizetable[qh->qhmem.indextable[insize]]; \
|
||||
qh->qhmem.totfree += qh->qhmem.sizetable[qh->qhmem.indextable[insize]]; \
|
||||
*((void **)object)= *freelistp;\
|
||||
*freelistp= object;}}
|
||||
#endif
|
||||
|
||||
/*=============== prototypes in alphabetical order ============*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *qh_memalloc(qhT *qh, int insize);
|
||||
void qh_memcheck(qhT *qh);
|
||||
void qh_memfree(qhT *qh, void *object, int insize);
|
||||
void qh_memfreeshort(qhT *qh, int *curlong, int *totlong);
|
||||
void qh_meminit(qhT *qh, FILE *ferr);
|
||||
void qh_meminitbuffers(qhT *qh, int tracelevel, int alignment, int numsizes,
|
||||
int bufsize, int bufinit);
|
||||
void qh_memsetup(qhT *qh);
|
||||
void qh_memsize(qhT *qh, int size);
|
||||
void qh_memstatistics(qhT *qh, FILE *fp);
|
||||
void qh_memtotal(qhT *qh, int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* qhDEFmem */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,238 @@
|
||||
/*<html><pre> -<a href="qh-merge_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
merge_r.h
|
||||
header file for merge_r.c
|
||||
|
||||
see qh-merge_r.htm and merge_r.c
|
||||
|
||||
Copyright (c) 1993-2020 C.B. Barber.
|
||||
$Id: //main/2019/qhull/src/libqhull_r/merge_r.h#2 $$Change: 2953 $
|
||||
$DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
|
||||
*/
|
||||
|
||||
#ifndef qhDEFmerge
|
||||
#define qhDEFmerge 1
|
||||
|
||||
#include "libqhull_r.h"
|
||||
|
||||
|
||||
/*============ -constants- ==============*/
|
||||
|
||||
/*-<a href="qh-merge_r.htm#TOC"
|
||||
>--------------------------------</a><a name="qh_ANGLEnone">-</a>
|
||||
|
||||
qh_ANGLEnone
|
||||
indicates missing angle for mergeT->angle
|
||||
*/
|
||||
#define qh_ANGLEnone 2.0
|
||||
|
||||
/*-<a href="qh-merge_r.htm#TOC"
|
||||
>--------------------------------</a><a name="MRG">-</a>
|
||||
|
||||
MRG... (mergeType)
|
||||
indicates the type of a merge (mergeT->type)
|
||||
MRGcoplanar...MRGtwisted set by qh_test_centrum_merge, qh_test_nonsimplicial_merge
|
||||
*/
|
||||
typedef enum { /* must match mergetypes[] */
|
||||
MRGnone= 0,
|
||||
/* MRGcoplanar..MRGtwisted go into qh.facet_mergeset for qh_all_merges
|
||||
qh_compare_facetmerge selects lower mergetypes for merging first */
|
||||
MRGcoplanar, /* (1) centrum coplanar if centrum ('Cn') or vertex not clearly above or below neighbor */
|
||||
MRGanglecoplanar, /* (2) angle coplanar if angle ('An') is coplanar */
|
||||
MRGconcave, /* (3) concave ridge */
|
||||
MRGconcavecoplanar, /* (4) concave and coplanar ridge, one side concave, other side coplanar */
|
||||
MRGtwisted, /* (5) twisted ridge, both concave and convex, facet1 is wider */
|
||||
/* MRGflip go into qh.facet_mergeset for qh_flipped_merges */
|
||||
MRGflip, /* (6) flipped facet if qh.interior_point is above facet, w/ facet1 == facet2 */
|
||||
/* MRGdupridge go into qh.facet_mergeset for qh_forcedmerges */
|
||||
MRGdupridge, /* (7) dupridge if more than two neighbors. Set by qh_mark_dupridges for qh_MERGEridge */
|
||||
/* MRGsubridge and MRGvertices go into vertex_mergeset */
|
||||
MRGsubridge, /* (8) merge pinched vertex to remove the subridge of a MRGdupridge */
|
||||
MRGvertices, /* (9) merge pinched vertex to remove a facet's ridges with the same vertices */
|
||||
/* MRGdegen, MRGredundant, and MRGmirror go into qh.degen_mergeset */
|
||||
MRGdegen, /* (10) degenerate facet (!enough neighbors) facet1 == facet2 */
|
||||
MRGredundant, /* (11) redundant facet (vertex subset) */
|
||||
/* merge_degenredundant assumes degen < redundant */
|
||||
MRGmirror, /* (12) mirror facets: same vertices due to null facets in qh_triangulate
|
||||
f.redundant for both facets*/
|
||||
/* MRGcoplanarhorizon for qh_mergecycle_all only */
|
||||
MRGcoplanarhorizon, /* (13) new facet coplanar with the horizon (qh_mergecycle_all) */
|
||||
ENDmrg
|
||||
} mergeType;
|
||||
|
||||
/*-<a href="qh-merge_r.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_r.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; /* cosine of angle between normals of facet1 and facet2,
|
||||
null value and right angle is 0.0, coplanar is 1.0, narrow is -1.0 */
|
||||
realT distance; /* absolute value of distance between vertices, centrum and facet, or vertex and facet */
|
||||
facetT *facet1; /* will merge facet1 into facet2 */
|
||||
facetT *facet2;
|
||||
vertexT *vertex1; /* will merge vertext1 into vertex2 for MRGsubridge or MRGvertices */
|
||||
vertexT *vertex2;
|
||||
ridgeT *ridge1; /* the duplicate ridges resolved by MRGvertices */
|
||||
ridgeT *ridge2; /* merge is deleted if either ridge is deleted (qh_delridge) */
|
||||
mergeType mergetype;
|
||||
};
|
||||
|
||||
|
||||
/*=========== -macros- =========================*/
|
||||
|
||||
/*-<a href="qh-merge_r.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 or use qh_setdellast() since qh.facet_mergeset may change
|
||||
see <a href="qset_r.h#FOREACHsetelement_">FOREACHsetelement_</a>
|
||||
*/
|
||||
#define FOREACHmerge_(merges) FOREACHsetelement_(mergeT, merges, merge)
|
||||
|
||||
/*-<a href="qh-poly_r.htm#TOC"
|
||||
>--------------------------------</a><a name="FOREACHmergeA_">-</a>
|
||||
|
||||
FOREACHmergeA_( vertices ) { ... }
|
||||
assign 'mergeA' to each merge in merges
|
||||
|
||||
notes:
|
||||
uses 'mergeT *mergeA, *mergeAp;'
|
||||
see <a href="qset_r.h#FOREACHsetelement_">FOREACHsetelement_</a>
|
||||
*/
|
||||
#define FOREACHmergeA_(merges) FOREACHsetelement_(mergeT, merges, mergeA)
|
||||
|
||||
/*-<a href="qh-poly_r.htm#TOC"
|
||||
>--------------------------------</a><a name="FOREACHmerge_i_">-</a>
|
||||
|
||||
FOREACHmerge_i_(qh, vertices ) { ... }
|
||||
assign 'merge' and 'merge_i' for each merge in mergeset
|
||||
|
||||
declare:
|
||||
mergeT *merge;
|
||||
int merge_n, merge_i;
|
||||
|
||||
see:
|
||||
<a href="qset_r.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
|
||||
*/
|
||||
#define FOREACHmerge_i_(qh, mergeset) FOREACHsetelement_i_(qh, mergeT, mergeset, merge)
|
||||
|
||||
/*============ prototypes in alphabetical order after pre/postmerge =======*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void qh_premerge(qhT *qh, int apexpointid, realT maxcentrum, realT maxangle);
|
||||
void qh_postmerge(qhT *qh, const char *reason, realT maxcentrum, realT maxangle,
|
||||
boolT vneighbors);
|
||||
void qh_all_merges(qhT *qh, boolT othermerge, boolT vneighbors);
|
||||
void qh_all_vertexmerges(qhT *qh, int apexpointid, facetT *facet, facetT **retryfacet);
|
||||
void qh_appendmergeset(qhT *qh, facetT *facet, facetT *neighbor, mergeType mergetype, coordT dist, realT angle);
|
||||
void qh_appendvertexmerge(qhT *qh, vertexT *vertex, vertexT *destination, mergeType mergetype, realT distance, ridgeT *ridge1, ridgeT *ridge2);
|
||||
setT *qh_basevertices(qhT *qh, facetT *samecycle);
|
||||
void qh_check_dupridge(qhT *qh, facetT *facet1, realT dist1, facetT *facet2, realT dist2);
|
||||
void qh_checkconnect(qhT *qh /* qh.new_facets */);
|
||||
void qh_checkdelfacet(qhT *qh, facetT *facet, setT *mergeset);
|
||||
void qh_checkdelridge(qhT *qh /* qh.visible_facets, vertex_mergeset */);
|
||||
boolT qh_checkzero(qhT *qh, boolT testall);
|
||||
int qh_compare_anglemerge(const void *p1, const void *p2);
|
||||
int qh_compare_facetmerge(const void *p1, const void *p2);
|
||||
int qh_comparevisit(const void *p1, const void *p2);
|
||||
void qh_copynonconvex(qhT *qh, ridgeT *atridge);
|
||||
void qh_degen_redundant_facet(qhT *qh, facetT *facet);
|
||||
void qh_drop_mergevertex(qhT *qh, mergeT *merge);
|
||||
void qh_delridge_merge(qhT *qh, ridgeT *ridge);
|
||||
vertexT *qh_find_newvertex(qhT *qh, vertexT *oldvertex, setT *vertices, setT *ridges);
|
||||
vertexT *qh_findbest_pinchedvertex(qhT *qh, mergeT *merge, vertexT *apex, vertexT **pinchedp, realT *distp /* qh.newfacet_list */);
|
||||
vertexT *qh_findbest_ridgevertex(qhT *qh, ridgeT *ridge, vertexT **pinchedp, coordT *distp);
|
||||
void qh_findbest_test(qhT *qh, boolT testcentrum, facetT *facet, facetT *neighbor,
|
||||
facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp);
|
||||
facetT *qh_findbestneighbor(qhT *qh, facetT *facet, realT *distp, realT *mindistp, realT *maxdistp);
|
||||
void qh_flippedmerges(qhT *qh, facetT *facetlist, boolT *wasmerge);
|
||||
void qh_forcedmerges(qhT *qh, boolT *wasmerge);
|
||||
void qh_freemergesets(qhT *qh);
|
||||
void qh_getmergeset(qhT *qh, facetT *facetlist);
|
||||
void qh_getmergeset_initial(qhT *qh, facetT *facetlist);
|
||||
boolT qh_getpinchedmerges(qhT *qh, vertexT *apex, coordT maxdupdist, boolT *iscoplanar /* qh.newfacet_list, vertex_mergeset */);
|
||||
boolT qh_hasmerge(setT *mergeset, mergeType type, facetT *facetA, facetT *facetB);
|
||||
void qh_hashridge(qhT *qh, setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex);
|
||||
ridgeT *qh_hashridge_find(qhT *qh, setT *hashtable, int hashsize, ridgeT *ridge,
|
||||
vertexT *vertex, vertexT *oldvertex, int *hashslot);
|
||||
void qh_initmergesets(qhT *qh);
|
||||
void qh_makeridges(qhT *qh, facetT *facet);
|
||||
void qh_mark_dupridges(qhT *qh, facetT *facetlist, boolT allmerges);
|
||||
void qh_maybe_duplicateridge(qhT *qh, ridgeT *ridge);
|
||||
void qh_maybe_duplicateridges(qhT *qh, facetT *facet);
|
||||
void qh_maydropneighbor(qhT *qh, facetT *facet);
|
||||
int qh_merge_degenredundant(qhT *qh);
|
||||
void qh_merge_nonconvex(qhT *qh, facetT *facet1, facetT *facet2, mergeType mergetype);
|
||||
void qh_merge_pinchedvertices(qhT *qh, int apexpointid /* qh.newfacet_list */);
|
||||
void qh_merge_twisted(qhT *qh, facetT *facet1, facetT *facet2);
|
||||
void qh_mergecycle(qhT *qh, facetT *samecycle, facetT *newfacet);
|
||||
void qh_mergecycle_all(qhT *qh, facetT *facetlist, boolT *wasmerge);
|
||||
void qh_mergecycle_facets(qhT *qh, facetT *samecycle, facetT *newfacet);
|
||||
void qh_mergecycle_neighbors(qhT *qh, facetT *samecycle, facetT *newfacet);
|
||||
void qh_mergecycle_ridges(qhT *qh, facetT *samecycle, facetT *newfacet);
|
||||
void qh_mergecycle_vneighbors(qhT *qh, facetT *samecycle, facetT *newfacet);
|
||||
void qh_mergefacet(qhT *qh, facetT *facet1, facetT *facet2, mergeType mergetype, realT *mindist, realT *maxdist, boolT mergeapex);
|
||||
void qh_mergefacet2d(qhT *qh, facetT *facet1, facetT *facet2);
|
||||
void qh_mergeneighbors(qhT *qh, facetT *facet1, facetT *facet2);
|
||||
void qh_mergeridges(qhT *qh, facetT *facet1, facetT *facet2);
|
||||
void qh_mergesimplex(qhT *qh, facetT *facet1, facetT *facet2, boolT mergeapex);
|
||||
void qh_mergevertex_del(qhT *qh, vertexT *vertex, facetT *facet1, facetT *facet2);
|
||||
void qh_mergevertex_neighbors(qhT *qh, facetT *facet1, facetT *facet2);
|
||||
void qh_mergevertices(qhT *qh, setT *vertices1, setT **vertices);
|
||||
setT *qh_neighbor_intersections(qhT *qh, vertexT *vertex);
|
||||
setT *qh_neighbor_vertices(qhT *qh, vertexT *vertex, setT *subridge);
|
||||
void qh_neighbor_vertices_facet(qhT *qh, vertexT *vertexA, facetT *facet, setT **vertices);
|
||||
void qh_newvertices(qhT *qh, setT *vertices);
|
||||
mergeT *qh_next_vertexmerge(qhT *qh);
|
||||
facetT *qh_opposite_horizonfacet(qhT *qh, mergeT *merge, vertexT **vertex);
|
||||
boolT qh_reducevertices(qhT *qh);
|
||||
vertexT *qh_redundant_vertex(qhT *qh, vertexT *vertex);
|
||||
boolT qh_remove_extravertices(qhT *qh, facetT *facet);
|
||||
void qh_remove_mergetype(qhT *qh, setT *mergeset, mergeType type);
|
||||
void qh_rename_adjacentvertex(qhT *qh, vertexT *oldvertex, vertexT *newvertex, realT dist);
|
||||
vertexT *qh_rename_sharedvertex(qhT *qh, vertexT *vertex, facetT *facet);
|
||||
boolT qh_renameridgevertex(qhT *qh, ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex);
|
||||
void qh_renamevertex(qhT *qh, vertexT *oldvertex, vertexT *newvertex, setT *ridges,
|
||||
facetT *oldfacet, facetT *neighborA);
|
||||
boolT qh_test_appendmerge(qhT *qh, facetT *facet, facetT *neighbor, boolT simplicial);
|
||||
void qh_test_degen_neighbors(qhT *qh, facetT *facet);
|
||||
boolT qh_test_centrum_merge(qhT *qh, facetT *facet, facetT *neighbor, realT angle, boolT okangle);
|
||||
boolT qh_test_nonsimplicial_merge(qhT *qh, facetT *facet, facetT *neighbor, realT angle, boolT okangle);
|
||||
void qh_test_redundant_neighbors(qhT *qh, facetT *facet);
|
||||
boolT qh_test_vneighbors(qhT *qh /* qh.newfacet_list */);
|
||||
void qh_tracemerge(qhT *qh, facetT *facet1, facetT *facet2, mergeType mergetype);
|
||||
void qh_tracemerging(qhT *qh);
|
||||
void qh_undo_newfacets(qhT *qh);
|
||||
void qh_updatetested(qhT *qh, facetT *facet1, facetT *facet2);
|
||||
setT *qh_vertexridges(qhT *qh, vertexT *vertex, boolT allneighbors);
|
||||
void qh_vertexridges_facet(qhT *qh, vertexT *vertex, facetT *facet, setT **ridges);
|
||||
void qh_willdelete(qhT *qh, facetT *facet, facetT *replace);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* qhDEFmerge */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,310 @@
|
||||
/*<html><pre> -<a href="qh-poly_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
poly_r.h
|
||||
header file for poly_r.c and poly2_r.c
|
||||
|
||||
see qh-poly_r.htm, libqhull_r.h and poly_r.c
|
||||
|
||||
Copyright (c) 1993-2020 The Geometry Center.
|
||||
$Id: //main/2019/qhull/src/libqhull_r/poly_r.h#5 $$Change: 2963 $
|
||||
$DateTime: 2020/06/03 19:31:01 $$Author: bbarber $
|
||||
*/
|
||||
|
||||
#ifndef qhDEFpoly
|
||||
#define qhDEFpoly 1
|
||||
|
||||
#include "libqhull_r.h"
|
||||
|
||||
/*=============== constants ========================== */
|
||||
|
||||
/*-<a href="qh-geom_r.htm#TOC"
|
||||
>--------------------------------</a><a name="ALGORITHMfault">-</a>
|
||||
|
||||
qh_ALGORITHMfault
|
||||
use as argument to checkconvex() to report errors during buildhull
|
||||
*/
|
||||
#define qh_ALGORITHMfault 0
|
||||
|
||||
/*-<a href="qh-poly_r.htm#TOC"
|
||||
>--------------------------------</a><a name="DATAfault">-</a>
|
||||
|
||||
qh_DATAfault
|
||||
use as argument to checkconvex() to report errors during initialhull
|
||||
*/
|
||||
#define qh_DATAfault 1
|
||||
|
||||
/*-<a href="qh-poly_r.htm#TOC"
|
||||
>--------------------------------</a><a name="DUPLICATEridge">-</a>
|
||||
|
||||
qh_DUPLICATEridge
|
||||
special value for facet->neighbor to indicate a duplicate ridge
|
||||
|
||||
notes:
|
||||
set by qh_matchneighbor for qh_matchdupridge
|
||||
*/
|
||||
#define qh_DUPLICATEridge (facetT *)1L
|
||||
|
||||
/*-<a href="qh-poly_r.htm#TOC"
|
||||
>--------------------------------</a><a name="MERGEridge">-</a>
|
||||
|
||||
qh_MERGEridge flag in facet
|
||||
special value for facet->neighbor to indicate a duplicate ridge that needs merging
|
||||
|
||||
notes:
|
||||
set by qh_matchnewfacets..qh_matchdupridge from qh_DUPLICATEridge
|
||||
used by qh_mark_dupridges to set facet->mergeridge, facet->mergeridge2 from facet->dupridge
|
||||
*/
|
||||
#define qh_MERGEridge (facetT *)2L
|
||||
|
||||
|
||||
/*============ -structures- ====================*/
|
||||
|
||||
/*=========== -macros- =========================*/
|
||||
|
||||
/*-<a href="qh-poly_r.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_r.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_r.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_r.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_r.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_r.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_r.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_r.h#FOREACHsetelement_">FOREACHsetelement_</a>
|
||||
*/
|
||||
#define FOREACHneighborA_(facet) FOREACHsetelement_(facetT, facet->neighbors, neighborA)
|
||||
|
||||
/*-<a href="qh-poly_r.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_r.h#FOREACHsetelement_">FOREACHsetelement_</a>
|
||||
*/
|
||||
#define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible)
|
||||
|
||||
/*-<a href="qh-poly_r.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_r.h#FOREACHsetelement_">FOREACHsetelement_</a>
|
||||
*/
|
||||
#define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet)
|
||||
|
||||
/*-<a href="qh-poly_r.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_r.h#FOREACHsetelement_">FOREACHsetelement_</a>
|
||||
*/
|
||||
#define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA)
|
||||
|
||||
/*-<a href="qh-poly_r.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_r.h#FOREACHsetelement_">FOREACHsetelement_</a>
|
||||
*/
|
||||
#define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)
|
||||
|
||||
|
||||
/*=============== prototypes poly_r.c in alphabetical order ================*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void qh_appendfacet(qhT *qh, facetT *facet);
|
||||
void qh_appendvertex(qhT *qh, vertexT *vertex);
|
||||
void qh_attachnewfacets(qhT *qh /* qh.visible_list, qh.newfacet_list */);
|
||||
boolT qh_checkflipped(qhT *qh, facetT *facet, realT *dist, boolT allerror);
|
||||
void qh_delfacet(qhT *qh, facetT *facet);
|
||||
void qh_deletevisible(qhT *qh /* qh.visible_list, qh.horizon_list */);
|
||||
setT *qh_facetintersect(qhT *qh, facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra);
|
||||
int qh_gethash(qhT *qh, int hashsize, setT *set, int size, int firstindex, void *skipelem);
|
||||
facetT *qh_getreplacement(qhT *qh, facetT *visible);
|
||||
facetT *qh_makenewfacet(qhT *qh, setT *vertices, boolT toporient, facetT *facet);
|
||||
void qh_makenewplanes(qhT *qh /* qh.newfacet_list */);
|
||||
facetT *qh_makenew_nonsimplicial(qhT *qh, facetT *visible, vertexT *apex, int *numnew);
|
||||
facetT *qh_makenew_simplicial(qhT *qh, facetT *visible, vertexT *apex, int *numnew);
|
||||
void qh_matchneighbor(qhT *qh, facetT *newfacet, int newskip, int hashsize,
|
||||
int *hashcount);
|
||||
coordT qh_matchnewfacets(qhT *qh);
|
||||
boolT qh_matchvertices(qhT *qh, int firstindex, setT *verticesA, int skipA,
|
||||
setT *verticesB, int *skipB, boolT *same);
|
||||
facetT *qh_newfacet(qhT *qh);
|
||||
ridgeT *qh_newridge(qhT *qh);
|
||||
int qh_pointid(qhT *qh, pointT *point);
|
||||
void qh_removefacet(qhT *qh, facetT *facet);
|
||||
void qh_removevertex(qhT *qh, vertexT *vertex);
|
||||
void qh_update_vertexneighbors(qhT *qh);
|
||||
void qh_update_vertexneighbors_cone(qhT *qh);
|
||||
|
||||
|
||||
/*========== -prototypes poly2_r.c in alphabetical order ===========*/
|
||||
|
||||
boolT qh_addfacetvertex(qhT *qh, facetT *facet, vertexT *newvertex);
|
||||
void qh_addhash(void *newelem, setT *hashtable, int hashsize, int hash);
|
||||
void qh_check_bestdist(qhT *qh);
|
||||
void qh_check_maxout(qhT *qh);
|
||||
void qh_check_output(qhT *qh);
|
||||
void qh_check_point(qhT *qh, pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2, int *errcount);
|
||||
void qh_check_points(qhT *qh);
|
||||
void qh_checkconvex(qhT *qh, facetT *facetlist, int fault);
|
||||
void qh_checkfacet(qhT *qh, facetT *facet, boolT newmerge, boolT *waserrorp);
|
||||
void qh_checkflipped_all(qhT *qh, facetT *facetlist);
|
||||
boolT qh_checklists(qhT *qh, facetT *facetlist);
|
||||
void qh_checkpolygon(qhT *qh, facetT *facetlist);
|
||||
void qh_checkvertex(qhT *qh, vertexT *vertex, boolT allchecks, boolT *waserrorp);
|
||||
void qh_clearcenters(qhT *qh, qh_CENTER type);
|
||||
void qh_createsimplex(qhT *qh, setT *vertices);
|
||||
void qh_delridge(qhT *qh, ridgeT *ridge);
|
||||
void qh_delvertex(qhT *qh, vertexT *vertex);
|
||||
setT *qh_facet3vertex(qhT *qh, facetT *facet);
|
||||
facetT *qh_findbestfacet(qhT *qh, pointT *point, boolT bestoutside,
|
||||
realT *bestdist, boolT *isoutside);
|
||||
facetT *qh_findbestlower(qhT *qh, facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart);
|
||||
facetT *qh_findfacet_all(qhT *qh, pointT *point, boolT noupper, realT *bestdist, boolT *isoutside,
|
||||
int *numpart);
|
||||
int qh_findgood(qhT *qh, facetT *facetlist, int goodhorizon);
|
||||
void qh_findgood_all(qhT *qh, facetT *facetlist);
|
||||
void qh_furthestnext(qhT *qh /* qh.facet_list */);
|
||||
void qh_furthestout(qhT *qh, facetT *facet);
|
||||
void qh_infiniteloop(qhT *qh, facetT *facet);
|
||||
void qh_initbuild(qhT *qh);
|
||||
void qh_initialhull(qhT *qh, setT *vertices);
|
||||
setT *qh_initialvertices(qhT *qh, int dim, setT *maxpoints, pointT *points, int numpoints);
|
||||
vertexT *qh_isvertex(pointT *point, setT *vertices);
|
||||
vertexT *qh_makenewfacets(qhT *qh, pointT *point /* qh.horizon_list, visible_list */);
|
||||
coordT qh_matchdupridge(qhT *qh, facetT *atfacet, int atskip, int hashsize, int *hashcount);
|
||||
void qh_nearcoplanar(qhT *qh /* qh.facet_list */);
|
||||
vertexT *qh_nearvertex(qhT *qh, facetT *facet, pointT *point, realT *bestdistp);
|
||||
int qh_newhashtable(qhT *qh, int newsize);
|
||||
vertexT *qh_newvertex(qhT *qh, pointT *point);
|
||||
facetT *qh_nextfacet2d(facetT *facet, vertexT **nextvertexp);
|
||||
ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp);
|
||||
vertexT *qh_opposite_vertex(qhT *qh, facetT *facetA, facetT *neighbor);
|
||||
void qh_outcoplanar(qhT *qh /* qh.facet_list */);
|
||||
pointT *qh_point(qhT *qh, int id);
|
||||
void qh_point_add(qhT *qh, setT *set, pointT *point, void *elem);
|
||||
setT *qh_pointfacet(qhT *qh /* qh.facet_list */);
|
||||
setT *qh_pointvertex(qhT *qh /* qh.facet_list */);
|
||||
void qh_prependfacet(qhT *qh, facetT *facet, facetT **facetlist);
|
||||
void qh_printhashtable(qhT *qh, FILE *fp);
|
||||
void qh_printlists(qhT *qh);
|
||||
void qh_replacefacetvertex(qhT *qh, facetT *facet, vertexT *oldvertex, vertexT *newvertex);
|
||||
void qh_resetlists(qhT *qh, boolT stats, boolT resetVisible /* qh.newvertex_list qh.newfacet_list qh.visible_list */);
|
||||
void qh_setvoronoi_all(qhT *qh);
|
||||
void qh_triangulate(qhT *qh /* qh.facet_list */);
|
||||
void qh_triangulate_facet(qhT *qh, facetT *facetA, vertexT **first_vertex);
|
||||
void qh_triangulate_link(qhT *qh, facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB);
|
||||
void qh_triangulate_mirror(qhT *qh, facetT *facetA, facetT *facetB);
|
||||
void qh_triangulate_null(qhT *qh, facetT *facetA);
|
||||
void qh_vertexintersect(qhT *qh, setT **vertexsetA,setT *vertexsetB);
|
||||
setT *qh_vertexintersect_new(qhT *qh, setT *vertexsetA,setT *vertexsetB);
|
||||
void qh_vertexneighbors(qhT *qh /* qh.facet_list */);
|
||||
boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* qhDEFpoly */
|
||||
@@ -0,0 +1,161 @@
|
||||
/*<html><pre> -<a href="qh-qhull_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
qhull_ra.h
|
||||
all header files for compiling qhull with reentrant code
|
||||
included before C++ headers for user_r.h:QHULL_CRTDBG
|
||||
|
||||
see qh-qhull.htm
|
||||
|
||||
see libqhull_r.h for user-level definitions
|
||||
|
||||
see user_r.h for user-definable constants
|
||||
|
||||
defines internal functions for libqhull_r.c global_r.c
|
||||
|
||||
Copyright (c) 1993-2020 The Geometry Center.
|
||||
$Id: //main/2019/qhull/src/libqhull_r/qhull_ra.h#2 $$Change: 2953 $
|
||||
$DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
|
||||
|
||||
Notes: grep for ((" and (" to catch fprintf("lkasdjf");
|
||||
full parens around (x?y:z)
|
||||
use '#include "libqhull_r/qhull_ra.h"' to avoid name clashes
|
||||
*/
|
||||
|
||||
#ifndef qhDEFqhulla
|
||||
#define qhDEFqhulla 1
|
||||
|
||||
#include "libqhull_r.h" /* Includes user_r.h and data types */
|
||||
|
||||
#include "stat_r.h"
|
||||
#include "random_r.h"
|
||||
#include "mem_r.h"
|
||||
#include "qset_r.h"
|
||||
#include "geom_r.h"
|
||||
#include "merge_r.h"
|
||||
#include "poly_r.h"
|
||||
#include "io_r.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>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
/*** uncomment here and qset_r.c
|
||||
if string.h does not define memcpy()
|
||||
#include <memory.h>
|
||||
*/
|
||||
|
||||
#if qh_CLOCKtype == 2 /* defined in user_r.h from libqhull_r.h */
|
||||
#include <sys/types.h>
|
||||
#include <sys/times.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER /* Microsoft Visual C++ -- warning level 4 */
|
||||
#pragma warning( disable : 4100) /* unreferenced formal parameter */
|
||||
#pragma warning( disable : 4127) /* conditional expression is constant */
|
||||
#pragma warning( disable : 4706) /* assignment within conditional function */
|
||||
#pragma warning( disable : 4996) /* function was declared deprecated(strcpy, localtime, etc.) */
|
||||
#endif
|
||||
|
||||
/* ======= -macros- =========== */
|
||||
|
||||
/*-<a href="qh-qhull_r.htm#TOC"
|
||||
>--------------------------------</a><a name="traceN">-</a>
|
||||
|
||||
traceN((qh, qh->ferr, 0Nnnn, "format\n", vars));
|
||||
calls qh_fprintf if qh.IStracing >= N
|
||||
|
||||
Add debugging traps to the end of qh_fprintf
|
||||
|
||||
notes:
|
||||
removing tracing reduces code size but doesn't change execution speed
|
||||
*/
|
||||
#ifndef qh_NOtrace
|
||||
#define trace0(args) {if (qh->IStracing) qh_fprintf args;}
|
||||
#define trace1(args) {if (qh->IStracing >= 1) qh_fprintf args;}
|
||||
#define trace2(args) {if (qh->IStracing >= 2) qh_fprintf args;}
|
||||
#define trace3(args) {if (qh->IStracing >= 3) qh_fprintf args;}
|
||||
#define trace4(args) {if (qh->IStracing >= 4) qh_fprintf args;}
|
||||
#define trace5(args) {if (qh->IStracing >= 5) qh_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 */
|
||||
|
||||
/*-<a href="qh-qhull_r.htm#TOC"
|
||||
>--------------------------------</a><a name="QHULL_UNUSED">-</a>
|
||||
|
||||
Define an unused variable to avoid compiler warnings
|
||||
|
||||
Derived from Qt's corelib/global/qglobal.h
|
||||
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus) && defined(__INTEL_COMPILER) && !defined(QHULL_OS_WIN)
|
||||
template <typename T>
|
||||
inline void qhullUnused(T &x) { (void)x; }
|
||||
# define QHULL_UNUSED(x) qhullUnused(x);
|
||||
#else
|
||||
# define QHULL_UNUSED(x) (void)x;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***** -libqhull_r.c prototypes (alphabetical after qhull) ********************/
|
||||
|
||||
void qh_qhull(qhT *qh);
|
||||
boolT qh_addpoint(qhT *qh, pointT *furthest, facetT *facet, boolT checkdist);
|
||||
void qh_build_withrestart(qhT *qh);
|
||||
vertexT *qh_buildcone(qhT *qh, pointT *furthest, facetT *facet, int goodhorizon, facetT **retryfacet);
|
||||
boolT qh_buildcone_mergepinched(qhT *qh, vertexT *apex, facetT *facet, facetT **retryfacet);
|
||||
boolT qh_buildcone_onlygood(qhT *qh, vertexT *apex, int goodhorizon);
|
||||
void qh_buildhull(qhT *qh);
|
||||
void qh_buildtracing(qhT *qh, pointT *furthest, facetT *facet);
|
||||
void qh_errexit2(qhT *qh, int exitcode, facetT *facet, facetT *otherfacet);
|
||||
void qh_findhorizon(qhT *qh, pointT *point, facetT *facet, int *goodvisible,int *goodhorizon);
|
||||
pointT *qh_nextfurthest(qhT *qh, facetT **visible);
|
||||
void qh_partitionall(qhT *qh, setT *vertices, pointT *points,int npoints);
|
||||
void qh_partitioncoplanar(qhT *qh, pointT *point, facetT *facet, realT *dist, boolT allnew);
|
||||
void qh_partitionpoint(qhT *qh, pointT *point, facetT *facet);
|
||||
void qh_partitionvisible(qhT *qh, boolT allpoints, int *numpoints);
|
||||
void qh_joggle_restart(qhT *qh, const char *reason);
|
||||
void qh_printsummary(qhT *qh, FILE *fp);
|
||||
|
||||
/***** -global_r.c internal prototypes (alphabetical) ***********************/
|
||||
|
||||
void qh_appendprint(qhT *qh, qh_PRINT format);
|
||||
void qh_freebuild(qhT *qh, boolT allmem);
|
||||
void qh_freebuffers(qhT *qh);
|
||||
void qh_initbuffers(qhT *qh, coordT *points, int numpoints, int dim, boolT ismalloc);
|
||||
|
||||
/***** -stat_r.c internal prototypes (alphabetical) ***********************/
|
||||
|
||||
void qh_allstatA(qhT *qh);
|
||||
void qh_allstatB(qhT *qh);
|
||||
void qh_allstatC(qhT *qh);
|
||||
void qh_allstatD(qhT *qh);
|
||||
void qh_allstatE(qhT *qh);
|
||||
void qh_allstatE2(qhT *qh);
|
||||
void qh_allstatF(qhT *qh);
|
||||
void qh_allstatG(qhT *qh);
|
||||
void qh_allstatH(qhT *qh);
|
||||
void qh_freebuffers(qhT *qh);
|
||||
void qh_initbuffers(qhT *qh, coordT *points, int numpoints, int dim, boolT ismalloc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* qhDEFqhulla */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,515 @@
|
||||
/*<html><pre> -<a href="qh-set_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
qset_r.h
|
||||
header file for qset_r.c that implements set
|
||||
|
||||
see qh-set_r.htm and qset_r.c
|
||||
|
||||
only uses mem_r.c, malloc/free
|
||||
|
||||
for error handling, writes message and calls
|
||||
qh_errexit(qhT *qh, 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-2020 The Geometry Center.
|
||||
$Id: //main/2019/qhull/src/libqhull_r/qset_r.h#4 $$Change: 2953 $
|
||||
$DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
|
||||
*/
|
||||
|
||||
#ifndef qhDEFset
|
||||
#define qhDEFset 1
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*================= -structures- ===============*/
|
||||
|
||||
#ifndef DEFsetT
|
||||
#define DEFsetT 1
|
||||
typedef struct setT setT; /* a set is a sorted or unsorted array of pointers */
|
||||
#endif
|
||||
|
||||
#ifndef DEFqhT
|
||||
#define DEFqhT 1
|
||||
typedef struct qhT qhT; /* defined in libqhull_r.h */
|
||||
#endif
|
||||
|
||||
/* [jan'15] Decided not to use countT. Most sets are small. The code uses signed tests */
|
||||
|
||||
/*-<a href="qh-set_r.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_r.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[]; /* 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_r.htm#TOC"
|
||||
>-----------------------------------</a><a name="SETelemsize">-</a>
|
||||
|
||||
SETelemsize
|
||||
size of a set element in bytes
|
||||
*/
|
||||
#define SETelemsize ((int)sizeof(setelemT))
|
||||
|
||||
/*
|
||||
SETbasesize - size of setT with a single element
|
||||
in e[]. Before C99, setT has been declared with e[1], so
|
||||
sizeof(setT) included already space for one element, but with e[]
|
||||
(C99), it does not. All instances of (int)sizeof(setT) have been
|
||||
replaced with SETbasesize throughout the code -- Tomas Kalibera,
|
||||
2025-01-09 */
|
||||
#define SETbasesize ((int)sizeof(setT) + SETelemsize)
|
||||
|
||||
|
||||
/*=========== -macros- =========================*/
|
||||
|
||||
/*-<a href="qh-set_r.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
|
||||
assumes set is not modified
|
||||
|
||||
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_r.htm#TOC"
|
||||
>----------------------------------------</a><a name="FOREACHsetelement_i_">-</a>
|
||||
|
||||
FOREACHsetelement_i_(qh, 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_(qh, facets) FOREACHsetelement_i_(qh, 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_(qh, type, set, variable) \
|
||||
if (((variable= NULL), set)) for (\
|
||||
variable##_i= 0, variable= (type *)((set)->e[0].p), \
|
||||
variable##_n= qh_setsize(qh, set);\
|
||||
variable##_i < variable##_n;\
|
||||
variable= (type *)((set)->e[++variable##_i].p) )
|
||||
|
||||
/*-<a href="qh-set_r.htm#TOC"
|
||||
>--------------------------------------</a><a name="FOREACHsetelementreverse_">-</a>
|
||||
|
||||
FOREACHsetelementreverse_(qh, 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_(qh, type, set, variable) \
|
||||
if (((variable= NULL), set)) for (\
|
||||
variable##temp= qh_setsize(qh, set)-1, variable= qh_setlast(qh, set);\
|
||||
variable; variable= \
|
||||
((--variable##temp >= 0) ? SETelemt_(set, variable##temp, type) : NULL))
|
||||
|
||||
/*-<a href="qh-set_r.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_r.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:
|
||||
assumes set is not modified
|
||||
WARNING: needs braces if nested inside another FOREACH
|
||||
*/
|
||||
#define FOREACHelem_(set) FOREACHsetelement_(void, set, elem)
|
||||
|
||||
/*-<a href="qh-set_r.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_r.htm#TOC"
|
||||
>-----------------------------------------</a><a name="SETindex_">-</a>
|
||||
|
||||
SETindex_( set, elem )
|
||||
return index of elem in set
|
||||
|
||||
notes:
|
||||
for use with FOREACH iteration
|
||||
WARN64 -- Maximum set size is 2G
|
||||
|
||||
example:
|
||||
i= SETindex_(ridges, ridge)
|
||||
*/
|
||||
#define SETindex_(set, elem) ((int)((void **)elem##p - (void **)&(set)->e[1].p))
|
||||
|
||||
/*-<a href="qh-set_r.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_r.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_r.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_r.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_r.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_r.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_r.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_r.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_r.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_r.htm#TOC"
|
||||
>---------------------------------------</a><a name="SETreturnsize_">-</a>
|
||||
|
||||
SETreturnsize_(set, size)
|
||||
return size of a set
|
||||
|
||||
notes:
|
||||
set must be defined
|
||||
use qh_setsize(qhT *qh, set) unless speed is critical
|
||||
*/
|
||||
#define SETreturnsize_(set, size) (((size)= ((set)->e[(set)->maxsize].i))?(--(size)):((size)= (set)->maxsize))
|
||||
|
||||
/*-<a href="qh-set_r.htm#TOC"
|
||||
>---------------------------------------</a><a name="SETempty_">-</a>
|
||||
|
||||
SETempty_(set)
|
||||
return true(1) if set is empty (i.e., FOREACHsetelement_ is empty)
|
||||
|
||||
notes:
|
||||
set may be NULL
|
||||
qh_setsize may be non-zero if first element is NULL
|
||||
*/
|
||||
#define SETempty_(set) (!set || (SETfirst_(set) ? 0 : 1))
|
||||
|
||||
/*-<a href="qh-set_r.htm#TOC"
|
||||
>-------------------------------<a name="SETsizeaddr_">-</a>
|
||||
|
||||
SETsizeaddr_(set)
|
||||
return pointer to 'actual size+1' of set (set CANNOT be NULL!!)
|
||||
Its type is setelemT* for strict aliasing
|
||||
All SETelemaddr_ must be cast to setelemT
|
||||
|
||||
|
||||
notes:
|
||||
*SETsizeaddr==NULL or e[*SETsizeaddr-1].p==NULL
|
||||
*/
|
||||
#define SETsizeaddr_(set) (&((set)->e[(set)->maxsize]))
|
||||
|
||||
/*-<a href="qh-set_r.htm#TOC"
|
||||
>---------------------------------------</a><a name="SETtruncate_">-</a>
|
||||
|
||||
SETtruncate_(set, size)
|
||||
truncate set to size
|
||||
|
||||
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 ============*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void qh_setaddsorted(qhT *qh, setT **setp, void *elem);
|
||||
void qh_setaddnth(qhT *qh, setT **setp, int nth, void *newelem);
|
||||
void qh_setappend(qhT *qh, setT **setp, void *elem);
|
||||
void qh_setappend_set(qhT *qh, setT **setp, setT *setA);
|
||||
void qh_setappend2ndlast(qhT *qh, setT **setp, void *elem);
|
||||
void qh_setcheck(qhT *qh, setT *set, const char *tname, unsigned int id);
|
||||
void qh_setcompact(qhT *qh, setT *set);
|
||||
setT *qh_setcopy(qhT *qh, setT *set, int extra);
|
||||
void *qh_setdel(setT *set, void *elem);
|
||||
void *qh_setdellast(setT *set);
|
||||
void *qh_setdelnth(qhT *qh, setT *set, int nth);
|
||||
void *qh_setdelnthsorted(qhT *qh, setT *set, int nth);
|
||||
void *qh_setdelsorted(setT *set, void *newelem);
|
||||
setT *qh_setduplicate(qhT *qh, setT *set, int elemsize);
|
||||
void **qh_setendpointer(setT *set);
|
||||
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(qhT *qh, setT **set);
|
||||
void qh_setfree2(qhT *qh, setT **setp, int elemsize);
|
||||
void qh_setfreelong(qhT *qh, setT **set);
|
||||
int qh_setin(setT *set, void *setelem);
|
||||
int qh_setindex(setT *set, void *setelem);
|
||||
void qh_setlarger(qhT *qh, setT **setp);
|
||||
int qh_setlarger_quick(qhT *qh, int setsize, int *newsize);
|
||||
void *qh_setlast(setT *set);
|
||||
setT *qh_setnew(qhT *qh, int size);
|
||||
setT *qh_setnew_delnthsorted(qhT *qh, setT *set, int size, int nth, int prepend);
|
||||
void qh_setprint(qhT *qh, FILE *fp, const char* string, setT *set);
|
||||
void qh_setreplace(qhT *qh, setT *set, void *oldelem, void *newelem);
|
||||
int qh_setsize(qhT *qh, setT *set);
|
||||
setT *qh_settemp(qhT *qh, int setsize);
|
||||
void qh_settempfree(qhT *qh, setT **set);
|
||||
void qh_settempfree_all(qhT *qh);
|
||||
setT *qh_settemppop(qhT *qh);
|
||||
void qh_settemppush(qhT *qh, setT *set);
|
||||
void qh_settruncate(qhT *qh, setT *set, int size);
|
||||
int qh_setunique(qhT *qh, setT **set, void *elem);
|
||||
void qh_setzero(qhT *qh, setT *set, int idx, int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* qhDEFset */
|
||||
@@ -0,0 +1,249 @@
|
||||
/*<html><pre> -<a href="index_r.htm#TOC"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
random_r.c and utilities
|
||||
Park & Miller's minimimal standard random number generator
|
||||
argc/argv conversion
|
||||
|
||||
Used by rbox. Do not use 'qh'
|
||||
*/
|
||||
|
||||
#include "libqhull_r.h"
|
||||
#include "random_r.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _MSC_VER /* Microsoft Visual C++ -- warning level 4 */
|
||||
#pragma warning( disable : 4706) /* assignment within conditional function */
|
||||
#pragma warning( disable : 4996) /* function was declared deprecated(strcpy, localtime, etc.) */
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-globa_r.htm#TOC"
|
||||
>-------------------------------</a><a name="argv_to_command">-</a>
|
||||
|
||||
qh_argv_to_command( argc, argv, command, max_size )
|
||||
|
||||
build command from argc/argv
|
||||
max_size is at least
|
||||
|
||||
returns:
|
||||
a space-delimited string of options (just as typed)
|
||||
returns false if max_size is too short
|
||||
|
||||
notes:
|
||||
silently removes
|
||||
makes option string easy to input and output
|
||||
matches qh_argv_to_command_size
|
||||
argc may be 0
|
||||
*/
|
||||
int qh_argv_to_command(int argc, char *argv[], char* command, int max_size) {
|
||||
int i, remaining;
|
||||
char *s;
|
||||
*command= '\0'; /* max_size > 0 */
|
||||
|
||||
if (argc) {
|
||||
if ((s= strrchr( argv[0], '\\')) /* get filename w/o .exe extension */
|
||||
|| (s= strrchr( argv[0], '/')))
|
||||
s++;
|
||||
else
|
||||
s= argv[0];
|
||||
if ((int)strlen(s) < max_size) /* WARN64 */
|
||||
strcpy(command, s);
|
||||
else
|
||||
goto error_argv;
|
||||
if ((s= strstr(command, ".EXE"))
|
||||
|| (s= strstr(command, ".exe")))
|
||||
*s= '\0';
|
||||
}
|
||||
for (i=1; i < argc; i++) {
|
||||
s= argv[i];
|
||||
remaining= max_size - (int)strlen(command) - (int)strlen(s) - 2; /* WARN64 */
|
||||
if (!*s || strchr(s, ' ')) {
|
||||
char *t= command + strlen(command);
|
||||
remaining -= 2;
|
||||
if (remaining < 0) {
|
||||
goto error_argv;
|
||||
}
|
||||
*t++= ' ';
|
||||
*t++= '"';
|
||||
while (*s) {
|
||||
if (*s == '"') {
|
||||
if (--remaining < 0)
|
||||
goto error_argv;
|
||||
*t++= '\\';
|
||||
}
|
||||
*t++= *s++;
|
||||
}
|
||||
*t++= '"';
|
||||
*t= '\0';
|
||||
}else if (remaining < 0) {
|
||||
goto error_argv;
|
||||
}else {
|
||||
strcat(command, " ");
|
||||
strcat(command, s);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
error_argv:
|
||||
return 0;
|
||||
} /* argv_to_command */
|
||||
|
||||
/*-<a href="qh-globa_r.htm#TOC"
|
||||
>-------------------------------</a><a name="argv_to_command_size">-</a>
|
||||
|
||||
qh_argv_to_command_size( argc, argv )
|
||||
|
||||
return size to allocate for qh_argv_to_command()
|
||||
|
||||
notes:
|
||||
only called from rbox with qh_errexit not enabled
|
||||
caller should report error if returned size is less than 1
|
||||
argc may be 0
|
||||
actual size is usually shorter
|
||||
*/
|
||||
int qh_argv_to_command_size(int argc, char *argv[]) {
|
||||
int count= 1; /* null-terminator if argc==0 */
|
||||
int i;
|
||||
char *s;
|
||||
|
||||
for (i=0; i<argc; i++){
|
||||
count += (int)strlen(argv[i]) + 1; /* WARN64 */
|
||||
if (i>0 && strchr(argv[i], ' ')) {
|
||||
count += 2; /* quote delimiters */
|
||||
for (s=argv[i]; *s; s++) {
|
||||
if (*s == '"') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
} /* argv_to_command_size */
|
||||
|
||||
/*-<a href="qh-geom_r.htm#TOC"
|
||||
>-------------------------------</a><a name="rand">-</a>
|
||||
|
||||
qh_rand()
|
||||
qh_srand(qh, seed )
|
||||
generate pseudo-random number between 1 and 2^31 -2
|
||||
|
||||
notes:
|
||||
For qhull and rbox, called from qh_RANDOMint(),etc. [user_r.h]
|
||||
|
||||
From Park & Miller's minimal 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
|
||||
*/
|
||||
|
||||
/* Global variables and constants */
|
||||
|
||||
#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 qh_rand(qhT *qh) {
|
||||
int lo, hi, test;
|
||||
int seed= qh->last_random;
|
||||
|
||||
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->last_random= seed;
|
||||
/* seed= seed < qh_RANDOMmax/2 ? 0 : qh_RANDOMmax; for testing */
|
||||
/* seed= qh_RANDOMmax; for testing */
|
||||
return seed;
|
||||
} /* rand */
|
||||
|
||||
void qh_srand(qhT *qh, int seed) {
|
||||
if (seed < 1)
|
||||
qh->last_random= 1;
|
||||
else if (seed >= qh_rand_m)
|
||||
qh->last_random= qh_rand_m - 1;
|
||||
else
|
||||
qh->last_random= seed;
|
||||
} /* qh_srand */
|
||||
|
||||
/*-<a href="qh-geom_r.htm#TOC"
|
||||
>-------------------------------</a><a name="randomfactor">-</a>
|
||||
|
||||
qh_randomfactor(qh, scale, offset )
|
||||
return a random factor r * scale + offset
|
||||
|
||||
notes:
|
||||
qh.RANDOMa/b are defined in global_r.c
|
||||
qh_RANDOMint requires 'qh'
|
||||
*/
|
||||
realT qh_randomfactor(qhT *qh, realT scale, realT offset) {
|
||||
realT randr;
|
||||
|
||||
randr= qh_RANDOMint;
|
||||
return randr * scale + offset;
|
||||
} /* randomfactor */
|
||||
|
||||
/*-<a href="qh-geom_r.htm#TOC"
|
||||
>-------------------------------</a><a name="randommatrix">-</a>
|
||||
|
||||
qh_randommatrix(qh, 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
|
||||
|
||||
notes:
|
||||
qh_RANDOMint requires 'qh'
|
||||
*/
|
||||
void qh_randommatrix(qhT *qh, 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-globa_r.htm#TOC"
|
||||
>-------------------------------</a><a name="strtol">-</a>
|
||||
|
||||
qh_strtol( s, endp) qh_strtod( s, endp)
|
||||
internal versions of strtol() and strtod()
|
||||
does not skip trailing spaces
|
||||
notes:
|
||||
some implementations of strtol()/strtod() skip trailing spaces
|
||||
*/
|
||||
double qh_strtod(const char *s, char **endp) {
|
||||
double result;
|
||||
|
||||
result= strtod(s, endp);
|
||||
if (s < (*endp) && (*endp)[-1] == ' ')
|
||||
(*endp)--;
|
||||
return result;
|
||||
} /* strtod */
|
||||
|
||||
int qh_strtol(const char *s, char **endp) {
|
||||
int result;
|
||||
|
||||
result= (int) strtol(s, endp, 10); /* WARN64 */
|
||||
if (s< (*endp) && (*endp)[-1] == ' ')
|
||||
(*endp)--;
|
||||
return result;
|
||||
} /* strtol */
|
||||
@@ -0,0 +1,41 @@
|
||||
/*<html><pre> -<a href="qh-geom_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
random_r.h
|
||||
header file for random and utility routines
|
||||
|
||||
see qh-geom_r.htm and random_r.c
|
||||
|
||||
Copyright (c) 1993-2020 The Geometry Center.
|
||||
$Id: //main/2019/qhull/src/libqhull_r/random_r.h#3 $$Change: 2953 $
|
||||
$DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
|
||||
*/
|
||||
|
||||
#ifndef qhDEFrandom
|
||||
#define qhDEFrandom 1
|
||||
|
||||
#include "libqhull_r.h"
|
||||
|
||||
/*============= prototypes in alphabetical order ======= */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int qh_argv_to_command(int argc, char *argv[], char* command, int max_size);
|
||||
int qh_argv_to_command_size(int argc, char *argv[]);
|
||||
int qh_rand(qhT *qh);
|
||||
void qh_srand(qhT *qh, int seed);
|
||||
realT qh_randomfactor(qhT *qh, realT scale, realT offset);
|
||||
void qh_randommatrix(qhT *qh, realT *buffer, int dim, realT **row);
|
||||
int qh_strtol(const char *s, char **endp);
|
||||
double qh_strtod(const char *s, char **endp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* qhDEFrandom */
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,854 @@
|
||||
/*<html><pre> -<a href="index_r.htm#TOC"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
rboxlib_r.c
|
||||
Generate input points
|
||||
|
||||
notes:
|
||||
For documentation, see prompt[] of rbox_r.c
|
||||
50 points generated for 'rbox D4'
|
||||
|
||||
WARNING:
|
||||
incorrect range if qh_RANDOMmax is defined wrong (user_r.h)
|
||||
*/
|
||||
|
||||
#include "libqhull_r.h" /* First for user_r.h */
|
||||
#include "random_r.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _MSC_VER /* Microsoft Visual C++ */
|
||||
#pragma warning( disable : 4706) /* assignment within conditional expression. */
|
||||
#pragma warning( disable : 4996) /* this function (strncat,sprintf,strcpy) or variable may be unsafe. */
|
||||
#endif
|
||||
|
||||
#define MAXdim 200
|
||||
#define PI 3.1415926535897932384
|
||||
|
||||
/* ------------------------------ prototypes ----------------*/
|
||||
int qh_roundi(qhT *qh, double a);
|
||||
void qh_out1(qhT *qh, double a);
|
||||
void qh_out2n(qhT *qh, double a, double b);
|
||||
void qh_out3n(qhT *qh, double a, double b, double c);
|
||||
void qh_outcoord(qhT *qh, int iscdd, double *coord, int dim);
|
||||
void qh_outcoincident(qhT *qh, int coincidentpoints, double radius, int iscdd, double *coord, int dim);
|
||||
void qh_rboxpoints2(qhT *qh, char* rbox_command, double **simplex);
|
||||
|
||||
void qh_fprintf_rbox(qhT *qh, FILE *fp, int msgcode, const char *fmt, ... );
|
||||
void qh_free(void *mem);
|
||||
void *qh_malloc(size_t size);
|
||||
int qh_rand(qhT *qh);
|
||||
void qh_srand(qhT *qh, int seed);
|
||||
|
||||
/*-<a href="qh-qhull_r.htm#TOC"
|
||||
>-------------------------------</a><a name="rboxpoints">-</a>
|
||||
|
||||
qh_rboxpoints(qh, rbox_command )
|
||||
Generate points to qh.fout according to rbox options
|
||||
Report errors on qh.ferr
|
||||
|
||||
returns:
|
||||
0 (qh_ERRnone) on success
|
||||
1 (qh_ERRinput) on input error
|
||||
4 (qh_ERRmem) on memory error
|
||||
5 (qh_ERRqhull) on internal error
|
||||
|
||||
notes:
|
||||
To avoid using stdio, redefine qh_malloc, qh_free, and qh_fprintf_rbox (user_r.c)
|
||||
Split out qh_rboxpoints2() to avoid -Wclobbered
|
||||
|
||||
design:
|
||||
Straight line code (consider defining a struct and functions):
|
||||
|
||||
Parse arguments into variables
|
||||
Determine the number of points
|
||||
Generate the points
|
||||
*/
|
||||
int qh_rboxpoints(qhT *qh, char* rbox_command) {
|
||||
int exitcode;
|
||||
double *simplex;
|
||||
|
||||
simplex= NULL;
|
||||
exitcode= setjmp(qh->rbox_errexit);
|
||||
if (exitcode) {
|
||||
/* same code for error exit and normal return. qh.NOerrexit is set */
|
||||
if (simplex)
|
||||
qh_free(simplex);
|
||||
return exitcode;
|
||||
}
|
||||
qh_rboxpoints2(qh, rbox_command, &simplex);
|
||||
/* same code for error exit and normal return */
|
||||
if (simplex)
|
||||
qh_free(simplex);
|
||||
return qh_ERRnone;
|
||||
} /* rboxpoints */
|
||||
|
||||
void qh_rboxpoints2(qhT *qh, char* rbox_command, double **simplex) {
|
||||
int i,j,k;
|
||||
int gendim;
|
||||
int coincidentcount=0, coincidenttotal=0, coincidentpoints=0;
|
||||
int cubesize, diamondsize, seed=0, count, apex;
|
||||
int dim=3, numpoints=0, totpoints, addpoints=0;
|
||||
int issphere=0, isaxis=0, iscdd=0, islens=0, isregular=0, iswidth=0, addcube=0;
|
||||
int isgap=0, isspiral=0, NOcommand=0, adddiamond=0;
|
||||
int israndom=0, istime=0;
|
||||
int isbox=0, issimplex=0, issimplex2=0, ismesh=0;
|
||||
double width=0.0, gap=0.0, radius=0.0, coincidentradius=0.0;
|
||||
double coord[MAXdim], offset, meshm=3.0, meshn=4.0, meshr=5.0;
|
||||
double *coordp, *simplexp;
|
||||
int nthroot, mult[MAXdim];
|
||||
double norm, factor, randr, rangap, tempr, lensangle=0, lensbase=1;
|
||||
double anglediff, angle, x, y, cube=0.0, diamond=0.0;
|
||||
double box= qh_DEFAULTbox; /* scale all numbers before output */
|
||||
double randmax= qh_RANDOMmax;
|
||||
char command[250], seedbuf[50];
|
||||
char *s=command, *t, *first_point=NULL;
|
||||
time_t timedata;
|
||||
|
||||
*command= '\0';
|
||||
strncat(command, rbox_command, sizeof(command)-sizeof(seedbuf)-strlen(command)-1);
|
||||
|
||||
while (*s && !isspace(*s)) /* skip program name */
|
||||
s++;
|
||||
while (*s) {
|
||||
while (*s && isspace(*s))
|
||||
s++;
|
||||
if (*s == '-')
|
||||
s++;
|
||||
if (!*s)
|
||||
break;
|
||||
if (isdigit(*s)) {
|
||||
numpoints= qh_strtol(s, &s);
|
||||
continue;
|
||||
}
|
||||
/* ============= read flags =============== */
|
||||
switch (*s++) {
|
||||
case 'c':
|
||||
addcube= 1;
|
||||
t= s;
|
||||
while (isspace(*t))
|
||||
t++;
|
||||
if (*t == 'G')
|
||||
cube= qh_strtod(++t, &s);
|
||||
break;
|
||||
case 'd':
|
||||
adddiamond= 1;
|
||||
t= s;
|
||||
while (isspace(*t))
|
||||
t++;
|
||||
if (*t == 'G')
|
||||
diamond= qh_strtod(++t, &s);
|
||||
break;
|
||||
case 'h':
|
||||
iscdd= 1;
|
||||
break;
|
||||
case 'l':
|
||||
isspiral= 1;
|
||||
break;
|
||||
case 'n':
|
||||
NOcommand= 1;
|
||||
break;
|
||||
case 'r':
|
||||
isregular= 1;
|
||||
break;
|
||||
case 's':
|
||||
issphere= 1;
|
||||
break;
|
||||
case 't':
|
||||
istime= 1;
|
||||
if (isdigit(*s)) {
|
||||
seed= qh_strtol(s, &s);
|
||||
israndom= 0;
|
||||
}else
|
||||
israndom= 1;
|
||||
break;
|
||||
case 'x':
|
||||
issimplex= 1;
|
||||
break;
|
||||
case 'y':
|
||||
issimplex2= 1;
|
||||
break;
|
||||
case 'z':
|
||||
qh->rbox_isinteger= 1;
|
||||
break;
|
||||
case 'B':
|
||||
box= qh_strtod(s, &s);
|
||||
isbox= 1;
|
||||
break;
|
||||
case 'C':
|
||||
if (*s)
|
||||
coincidentpoints= qh_strtol(s, &s);
|
||||
if (*s == ',') {
|
||||
++s;
|
||||
coincidentradius= qh_strtod(s, &s);
|
||||
}
|
||||
if (*s == ',') {
|
||||
++s;
|
||||
coincidenttotal= qh_strtol(s, &s);
|
||||
}
|
||||
if (*s && !isspace(*s)) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 7080, "rbox error: arguments for 'Cn,r,m' are not 'int', 'float', and 'int'. Remaining string is '%s'\n", s);
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
if (coincidentpoints==0){
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6268, "rbox error: missing arguments for 'Cn,r,m' where n is the number of coincident points, r is the radius (default 0.0), and m is the number of points\n");
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
if (coincidentpoints<0 || coincidenttotal<0 || coincidentradius<0.0){
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6269, "rbox error: negative arguments for 'Cn,m,r' where n (%d) is the number of coincident points, m (%d) is the number of points, and r (%.2g) is the radius (default 0.0)\n", coincidentpoints, coincidenttotal, coincidentradius);
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
dim= qh_strtol(s, &s);
|
||||
if (dim < 1
|
||||
|| dim > MAXdim) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6189, "rbox error: dimension, D%d, out of bounds (>=%d or <=0)\n", dim, MAXdim);
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
break;
|
||||
case 'G':
|
||||
if (isdigit(*s))
|
||||
gap= qh_strtod(s, &s);
|
||||
else
|
||||
gap= 0.5;
|
||||
isgap= 1;
|
||||
break;
|
||||
case 'L':
|
||||
if (isdigit(*s))
|
||||
radius= qh_strtod(s, &s);
|
||||
else
|
||||
radius= 10;
|
||||
islens= 1;
|
||||
break;
|
||||
case 'M':
|
||||
ismesh= 1;
|
||||
if (*s)
|
||||
meshn= qh_strtod(s, &s);
|
||||
if (*s == ',') {
|
||||
++s;
|
||||
meshm= qh_strtod(s, &s);
|
||||
}else
|
||||
meshm= 0.0;
|
||||
if (*s == ',') {
|
||||
++s;
|
||||
meshr= qh_strtod(s, &s);
|
||||
}else
|
||||
meshr= sqrt(meshn*meshn + meshm*meshm);
|
||||
if (*s && !isspace(*s)) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 7069, "rbox warning: assuming 'M3,4,5' since mesh args are not integers or reals\n");
|
||||
meshn= 3.0, meshm=4.0, meshr=5.0;
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
qh->rbox_out_offset= qh_strtod(s, &s);
|
||||
break;
|
||||
case 'P':
|
||||
if (!first_point)
|
||||
first_point= s - 1;
|
||||
addpoints++;
|
||||
while (*s && !isspace(*s)) /* read points later */
|
||||
s++;
|
||||
break;
|
||||
case 'W':
|
||||
width= qh_strtod(s, &s);
|
||||
iswidth= 1;
|
||||
break;
|
||||
case 'Z':
|
||||
if (isdigit(*s))
|
||||
radius= qh_strtod(s, &s);
|
||||
else
|
||||
radius= 1.0;
|
||||
isaxis= 1;
|
||||
break;
|
||||
default:
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6352, "rbox error: unknown flag at '%s'.\nExecute 'rbox' without arguments for documentation.\n", s - 1);
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
if (*s && !isspace(*s)) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6353, "rbox error: missing space between flags at %s.\n", s);
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
}
|
||||
|
||||
/* ============= defaults, constants, and sizes =============== */
|
||||
if (qh->rbox_isinteger && !isbox)
|
||||
box= qh_DEFAULTzbox;
|
||||
if (addcube) {
|
||||
tempr= floor(ldexp(1.0,dim)+0.5);
|
||||
cubesize= (int)tempr;
|
||||
if (cube == 0.0)
|
||||
cube= box;
|
||||
}else
|
||||
cubesize= 0;
|
||||
if (adddiamond) {
|
||||
diamondsize= 2*dim;
|
||||
if (diamond == 0.0)
|
||||
diamond= box;
|
||||
}else
|
||||
diamondsize= 0;
|
||||
if (islens) {
|
||||
if (isaxis) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6190, "rbox error: can not combine 'Ln' with 'Zn'\n");
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
if (radius <= 1.0) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6191, "rbox error: lens radius %.2g should be greater than 1.0\n",
|
||||
radius);
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
lensangle= asin(1.0/radius);
|
||||
lensbase= radius * cos(lensangle);
|
||||
}
|
||||
|
||||
if (!numpoints) {
|
||||
if (issimplex2)
|
||||
; /* ok */
|
||||
else if (isregular + issimplex + islens + issphere + isaxis + isspiral + iswidth + ismesh) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6192, "rbox error: missing count\n");
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}else if (adddiamond + addcube + addpoints)
|
||||
; /* ok */
|
||||
else {
|
||||
numpoints= 50; /* ./rbox D4 is the test case */
|
||||
issphere= 1;
|
||||
}
|
||||
}
|
||||
if ((issimplex + islens + isspiral + ismesh > 1)
|
||||
|| (issimplex + issphere + isspiral + ismesh > 1)) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6193, "rbox error: can only specify one of 'l', 's', 'x', 'Ln', or 'Mn,m,r' ('Ln s' is ok).\n");
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
if (coincidentpoints>0 && (numpoints == 0 || coincidenttotal > numpoints)) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6270, "rbox error: 'Cn,r,m' requested n coincident points for each of m points. Either there is no points or m (%d) is greater than the number of points (%d).\n", coincidenttotal, numpoints);
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
if (coincidentpoints > 0 && isregular) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6423, "rbox error: 'Cn,r,m' is not implemented for regular points ('r')\n");
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
|
||||
if (coincidenttotal == 0)
|
||||
coincidenttotal= numpoints;
|
||||
|
||||
/* ============= print header with total points =============== */
|
||||
if (issimplex || ismesh)
|
||||
totpoints= numpoints;
|
||||
else if (issimplex2)
|
||||
totpoints= numpoints+dim+1;
|
||||
else if (isregular) {
|
||||
totpoints= numpoints;
|
||||
if (dim == 2) {
|
||||
if (islens)
|
||||
totpoints += numpoints - 2;
|
||||
}else if (dim == 3) {
|
||||
if (islens)
|
||||
totpoints += 2 * numpoints;
|
||||
else if (isgap)
|
||||
totpoints += 1 + numpoints;
|
||||
else
|
||||
totpoints += 2;
|
||||
}
|
||||
}else
|
||||
totpoints= numpoints + isaxis;
|
||||
totpoints += cubesize + diamondsize + addpoints;
|
||||
totpoints += coincidentpoints*coincidenttotal;
|
||||
|
||||
/* ============= seed randoms =============== */
|
||||
if (istime == 0) {
|
||||
for (s=command; *s; s++) {
|
||||
if (issimplex2 && *s == 'y') /* make 'y' same seed as 'x' */
|
||||
i= 'x';
|
||||
else
|
||||
i= *s;
|
||||
seed= 11*seed + i;
|
||||
}
|
||||
}else if (israndom) {
|
||||
seed= (int)time(&timedata);
|
||||
snprintf(seedbuf, sizeof(seedbuf) / sizeof(seedbuf[0]), " t%d", seed); /* appends an extra t, not worth removing */
|
||||
strncat(command, seedbuf, sizeof(command) - strlen(command) - 1);
|
||||
t= strstr(command, " t ");
|
||||
if (t)
|
||||
strcpy(t+1, t+3); /* remove " t " */
|
||||
} /* else, seed explicitly set to n */
|
||||
qh_RANDOMseed_(qh, seed);
|
||||
|
||||
/* ============= print header =============== */
|
||||
|
||||
if (iscdd)
|
||||
qh_fprintf_rbox(qh, qh->fout, 9391, "%s\nbegin\n %d %d %s\n",
|
||||
NOcommand ? "" : command,
|
||||
totpoints, dim+1,
|
||||
qh->rbox_isinteger ? "integer" : "real");
|
||||
else if (NOcommand)
|
||||
qh_fprintf_rbox(qh, qh->fout, 9392, "%d\n%d\n", dim, totpoints);
|
||||
else
|
||||
/* qh_fprintf_rbox special cases 9393 to append 'command' to the RboxPoints.comment() */
|
||||
qh_fprintf_rbox(qh, qh->fout, 9393, "%d %s\n%d\n", dim, command, totpoints);
|
||||
|
||||
/* ============= explicit points =============== */
|
||||
if ((s= first_point)) {
|
||||
while (s && *s) { /* 'P' */
|
||||
count= 0;
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
while (*++s) {
|
||||
qh_out1(qh, qh_strtod(s, &s));
|
||||
count++;
|
||||
if (isspace(*s) || !*s)
|
||||
break;
|
||||
if (*s != ',') {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6194, "rbox error: missing comma after coordinate in %s\n\n", s);
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
}
|
||||
if (count < dim) {
|
||||
for (k=dim-count; k--; )
|
||||
qh_out1(qh, 0.0);
|
||||
}else if (count > dim) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6195, "rbox error: %d coordinates instead of %d coordinates in %s\n\n",
|
||||
count, dim, s);
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
qh_fprintf_rbox(qh, qh->fout, 9394, "\n");
|
||||
while ((s= strchr(s, 'P'))) {
|
||||
if (isspace(s[-1]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ============= simplex distribution =============== */
|
||||
if (issimplex+issimplex2) {
|
||||
if (!(*simplex= (double *)qh_malloc( (size_t)(dim * (dim+1)) * sizeof(double)))) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6196, "rbox error: insufficient memory for simplex\n");
|
||||
qh_errexit_rbox(qh, qh_ERRmem); /* qh_ERRmem */
|
||||
}
|
||||
simplexp= *simplex;
|
||||
if (isregular) {
|
||||
for (i=0; i<dim; i++) {
|
||||
for (k=0; k<dim; k++)
|
||||
*(simplexp++)= i==k ? 1.0 : 0.0;
|
||||
}
|
||||
for (k=0; k<dim; k++)
|
||||
*(simplexp++)= -1.0;
|
||||
}else {
|
||||
for (i=0; i<dim+1; i++) {
|
||||
for (k=0; k<dim; k++) {
|
||||
randr= qh_RANDOMint;
|
||||
*(simplexp++)= 2.0 * randr/randmax - 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (issimplex2) {
|
||||
simplexp= *simplex;
|
||||
for (i=0; i<dim+1; i++) {
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
for (k=0; k<dim; k++)
|
||||
qh_out1(qh, *(simplexp++) * box);
|
||||
qh_fprintf_rbox(qh, qh->fout, 9395, "\n");
|
||||
}
|
||||
}
|
||||
for (j=0; j<numpoints; j++) {
|
||||
if (iswidth)
|
||||
apex= qh_RANDOMint % (dim+1);
|
||||
else
|
||||
apex= -1;
|
||||
for (k=0; k<dim; k++)
|
||||
coord[k]= 0.0;
|
||||
norm= 0.0;
|
||||
for (i=0; i<dim+1; i++) {
|
||||
randr= qh_RANDOMint;
|
||||
factor= randr/randmax;
|
||||
if (i == apex)
|
||||
factor *= width;
|
||||
norm += factor;
|
||||
for (k=0; k<dim; k++) {
|
||||
simplexp= *simplex + i*dim + k;
|
||||
coord[k] += factor * (*simplexp);
|
||||
}
|
||||
}
|
||||
for (k=0; k<dim; k++)
|
||||
coord[k] *= box/norm;
|
||||
qh_outcoord(qh, iscdd, coord, dim);
|
||||
if(coincidentcount++ < coincidenttotal)
|
||||
qh_outcoincident(qh, coincidentpoints, coincidentradius, iscdd, coord, dim);
|
||||
}
|
||||
isregular= 0; /* continue with isbox */
|
||||
numpoints= 0;
|
||||
}
|
||||
|
||||
/* ============= mesh distribution =============== */
|
||||
if (ismesh) {
|
||||
nthroot= (int)(pow((double)numpoints, 1.0/dim) + 0.99999);
|
||||
for (k=dim; k--; )
|
||||
mult[k]= 0;
|
||||
for (i=0; i < numpoints; i++) {
|
||||
coordp= coord;
|
||||
for (k=0; k < dim; k++) {
|
||||
if (k == 0)
|
||||
*(coordp++)= mult[0] * meshn + mult[1] * (-meshm);
|
||||
else if (k == 1)
|
||||
*(coordp++)= mult[0] * meshm + mult[1] * meshn;
|
||||
else
|
||||
*(coordp++)= mult[k] * meshr;
|
||||
}
|
||||
qh_outcoord(qh, iscdd, coord, dim);
|
||||
if(coincidentcount++ < coincidenttotal)
|
||||
qh_outcoincident(qh, coincidentpoints, coincidentradius, iscdd, coord, dim);
|
||||
for (k=0; k < dim; k++) {
|
||||
if (++mult[k] < nthroot)
|
||||
break;
|
||||
mult[k]= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ============= regular points for 's' =============== */
|
||||
else if (isregular && !islens) {
|
||||
if (dim != 2 && dim != 3) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6197, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
if (!isaxis || radius == 0.0) {
|
||||
isaxis= 1;
|
||||
radius= 1.0;
|
||||
}
|
||||
if (dim == 3) {
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
qh_out3n(qh, 0.0, 0.0, -box);
|
||||
if (!isgap) {
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
qh_out3n(qh, 0.0, 0.0, box);
|
||||
}
|
||||
}
|
||||
angle= 0.0;
|
||||
anglediff= 2.0 * PI/numpoints;
|
||||
for (i=0; i < numpoints; i++) {
|
||||
angle += anglediff;
|
||||
x= radius * cos(angle);
|
||||
y= radius * sin(angle);
|
||||
if (dim == 2) {
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
qh_out2n(qh, x*box, y*box);
|
||||
}else {
|
||||
norm= sqrt(1.0 + x*x + y*y);
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
qh_out3n(qh, box*x/norm, box*y/norm, box/norm);
|
||||
if (isgap) {
|
||||
x *= 1-gap;
|
||||
y *= 1-gap;
|
||||
norm= sqrt(1.0 + x*x + y*y);
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
qh_out3n(qh, box*x/norm, box*y/norm, box/norm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ============= regular points for 'r Ln D2' =============== */
|
||||
else if (isregular && islens && dim == 2) {
|
||||
double cos_0;
|
||||
|
||||
angle= lensangle;
|
||||
anglediff= 2 * lensangle/(numpoints - 1);
|
||||
cos_0= cos(lensangle);
|
||||
for (i=0; i < numpoints; i++, angle -= anglediff) {
|
||||
x= radius * sin(angle);
|
||||
y= radius * (cos(angle) - cos_0);
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
qh_out2n(qh, x*box, y*box);
|
||||
if (i != 0 && i != numpoints - 1) {
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
qh_out2n(qh, x*box, -y*box);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ============= regular points for 'r Ln D3' =============== */
|
||||
else if (isregular && islens && dim != 2) {
|
||||
if (dim != 3) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6198, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
angle= 0.0;
|
||||
anglediff= 2* PI/numpoints;
|
||||
if (!isgap) {
|
||||
isgap= 1;
|
||||
gap= 0.5;
|
||||
}
|
||||
offset= sqrt(radius * radius - (1-gap)*(1-gap)) - lensbase;
|
||||
for (i=0; i < numpoints; i++, angle += anglediff) {
|
||||
x= cos(angle);
|
||||
y= sin(angle);
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
qh_out3n(qh, box*x, box*y, 0.0);
|
||||
x *= 1-gap;
|
||||
y *= 1-gap;
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
qh_out3n(qh, box*x, box*y, box * offset);
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
qh_out3n(qh, box*x, box*y, -box * offset);
|
||||
}
|
||||
}
|
||||
/* ============= apex of 'Zn' distribution + gendim =============== */
|
||||
else {
|
||||
if (isaxis) {
|
||||
gendim= dim-1;
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
for (j=0; j < gendim; j++)
|
||||
qh_out1(qh, 0.0);
|
||||
qh_out1(qh, -box);
|
||||
qh_fprintf_rbox(qh, qh->fout, 9398, "\n");
|
||||
}else if (islens)
|
||||
gendim= dim-1;
|
||||
else
|
||||
gendim= dim;
|
||||
/* ============= generate random point in unit cube =============== */
|
||||
for (i=0; i < numpoints; i++) {
|
||||
norm= 0.0;
|
||||
for (j=0; j < gendim; j++) {
|
||||
randr= qh_RANDOMint;
|
||||
coord[j]= 2.0 * randr/randmax - 1.0;
|
||||
norm += coord[j] * coord[j];
|
||||
}
|
||||
norm= sqrt(norm);
|
||||
/* ============= dim-1 point of 'Zn' distribution ========== */
|
||||
if (isaxis) {
|
||||
if (!isgap) {
|
||||
isgap= 1;
|
||||
gap= 1.0;
|
||||
}
|
||||
randr= qh_RANDOMint;
|
||||
rangap= 1.0 - gap * randr/randmax;
|
||||
factor= radius * rangap / norm;
|
||||
for (j=0; j<gendim; j++)
|
||||
coord[j]= factor * coord[j];
|
||||
/* ============= dim-1 point of 'Ln s' distribution =========== */
|
||||
}else if (islens && issphere) {
|
||||
if (!isgap) {
|
||||
isgap= 1;
|
||||
gap= 1.0;
|
||||
}
|
||||
randr= qh_RANDOMint;
|
||||
rangap= 1.0 - gap * randr/randmax;
|
||||
factor= rangap / norm;
|
||||
for (j=0; j<gendim; j++)
|
||||
coord[j]= factor * coord[j];
|
||||
/* ============= dim-1 point of 'Ln' distribution ========== */
|
||||
}else if (islens && !issphere) {
|
||||
if (!isgap) {
|
||||
isgap= 1;
|
||||
gap= 1.0;
|
||||
}
|
||||
j= qh_RANDOMint % gendim;
|
||||
if (coord[j] < 0)
|
||||
coord[j]= -1.0 - coord[j] * gap;
|
||||
else
|
||||
coord[j]= 1.0 - coord[j] * gap;
|
||||
/* ============= point of 'l' distribution =============== */
|
||||
}else if (isspiral) {
|
||||
if (dim != 3) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6199, "rbox error: spiral distribution is available only in 3d\n\n");
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
coord[0]= cos(2*PI*i/(numpoints - 1));
|
||||
coord[1]= sin(2*PI*i/(numpoints - 1));
|
||||
coord[2]= 2.0*(double)i/(double)(numpoints - 1) - 1.0;
|
||||
/* ============= point of 's' distribution =============== */
|
||||
}else if (issphere) {
|
||||
factor= 1.0/norm;
|
||||
if (iswidth) {
|
||||
randr= qh_RANDOMint;
|
||||
factor *= 1.0 - width * randr/randmax;
|
||||
}
|
||||
for (j=0; j<dim; j++)
|
||||
coord[j]= factor * coord[j];
|
||||
}
|
||||
/* ============= project 'Zn s' point in to sphere =============== */
|
||||
if (isaxis && issphere) {
|
||||
coord[dim-1]= 1.0;
|
||||
norm= 1.0;
|
||||
for (j=0; j<gendim; j++)
|
||||
norm += coord[j] * coord[j];
|
||||
norm= sqrt(norm);
|
||||
for (j=0; j<dim; j++)
|
||||
coord[j]= coord[j] / norm;
|
||||
if (iswidth) {
|
||||
randr= qh_RANDOMint;
|
||||
coord[dim-1] *= 1 - width * randr/randmax;
|
||||
}
|
||||
/* ============= project 'Zn' point onto cube =============== */
|
||||
}else if (isaxis && !issphere) { /* not very interesting */
|
||||
randr= qh_RANDOMint;
|
||||
coord[dim-1]= 2.0 * randr/randmax - 1.0;
|
||||
/* ============= project 'Ln' point out to sphere =============== */
|
||||
}else if (islens) {
|
||||
coord[dim-1]= lensbase;
|
||||
for (j=0, norm= 0; j<dim; j++)
|
||||
norm += coord[j] * coord[j];
|
||||
norm= sqrt(norm);
|
||||
for (j=0; j<dim; j++)
|
||||
coord[j]= coord[j] * radius/ norm;
|
||||
coord[dim-1] -= lensbase;
|
||||
if (iswidth) {
|
||||
randr= qh_RANDOMint;
|
||||
coord[dim-1] *= 1 - width * randr/randmax;
|
||||
}
|
||||
if (qh_RANDOMint > randmax/2)
|
||||
coord[dim-1]= -coord[dim-1];
|
||||
/* ============= project 'Wn' point toward boundary =============== */
|
||||
}else if (iswidth && !issphere) {
|
||||
j= qh_RANDOMint % gendim;
|
||||
if (coord[j] < 0)
|
||||
coord[j]= -1.0 - coord[j] * width;
|
||||
else
|
||||
coord[j]= 1.0 - coord[j] * width;
|
||||
}
|
||||
/* ============= scale point to box =============== */
|
||||
for (k=0; k<dim; k++)
|
||||
coord[k]= coord[k] * box;
|
||||
|
||||
/* ============= write output =============== */
|
||||
qh_outcoord(qh, iscdd, coord, dim);
|
||||
if(coincidentcount++ < coincidenttotal)
|
||||
qh_outcoincident(qh, coincidentpoints, coincidentradius, iscdd, coord, dim);
|
||||
}
|
||||
}
|
||||
|
||||
/* ============= write cube vertices =============== */
|
||||
if (addcube) {
|
||||
for (j=0; j<cubesize; j++) {
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
for (k=dim-1; k>=0; k--) {
|
||||
if (j & ( 1 << k))
|
||||
qh_out1(qh, cube);
|
||||
else
|
||||
qh_out1(qh, -cube);
|
||||
}
|
||||
qh_fprintf_rbox(qh, qh->fout, 9400, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* ============= write diamond vertices =============== */
|
||||
if (adddiamond) {
|
||||
for (j=0; j<diamondsize; j++) {
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
for (k=dim-1; k>=0; k--) {
|
||||
if (j/2 != k)
|
||||
qh_out1(qh, 0.0);
|
||||
else if (j & 0x1)
|
||||
qh_out1(qh, diamond);
|
||||
else
|
||||
qh_out1(qh, -diamond);
|
||||
}
|
||||
qh_fprintf_rbox(qh, qh->fout, 9401, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (iscdd)
|
||||
qh_fprintf_rbox(qh, qh->fout, 9402, "end\nhull\n");
|
||||
} /* rboxpoints2 */
|
||||
|
||||
/*------------------------------------------------
|
||||
outxxx - output functions for qh_rboxpoints
|
||||
*/
|
||||
int qh_roundi(qhT *qh, double a) {
|
||||
if (a < 0.0) {
|
||||
if (a - 0.5 < INT_MIN) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6200, "rbox input error: negative coordinate %2.2g is too large. Reduce 'Bn'\n", a);
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
return (int)(a - 0.5);
|
||||
}else {
|
||||
if (a + 0.5 > INT_MAX) {
|
||||
qh_fprintf_rbox(qh, qh->ferr, 6201, "rbox input error: coordinate %2.2g is too large. Reduce 'Bn'\n", a);
|
||||
qh_errexit_rbox(qh, qh_ERRinput);
|
||||
}
|
||||
return (int)(a + 0.5);
|
||||
}
|
||||
} /* qh_roundi */
|
||||
|
||||
void qh_out1(qhT *qh, double a) {
|
||||
|
||||
if (qh->rbox_isinteger)
|
||||
qh_fprintf_rbox(qh, qh->fout, 9403, "%d ", qh_roundi(qh, a+qh->rbox_out_offset));
|
||||
else
|
||||
qh_fprintf_rbox(qh, qh->fout, 9404, qh_REAL_1, a+qh->rbox_out_offset);
|
||||
} /* qh_out1 */
|
||||
|
||||
void qh_out2n(qhT *qh, double a, double b) {
|
||||
|
||||
if (qh->rbox_isinteger)
|
||||
qh_fprintf_rbox(qh, qh->fout, 9405, "%d %d\n", qh_roundi(qh, a+qh->rbox_out_offset), qh_roundi(qh, b+qh->rbox_out_offset));
|
||||
else
|
||||
qh_fprintf_rbox(qh, qh->fout, 9406, qh_REAL_2n, a+qh->rbox_out_offset, b+qh->rbox_out_offset);
|
||||
} /* qh_out2n */
|
||||
|
||||
void qh_out3n(qhT *qh, double a, double b, double c) {
|
||||
|
||||
if (qh->rbox_isinteger)
|
||||
qh_fprintf_rbox(qh, qh->fout, 9407, "%d %d %d\n", qh_roundi(qh, a+qh->rbox_out_offset), qh_roundi(qh, b+qh->rbox_out_offset), qh_roundi(qh, c+qh->rbox_out_offset));
|
||||
else
|
||||
qh_fprintf_rbox(qh, qh->fout, 9408, qh_REAL_3n, a+qh->rbox_out_offset, b+qh->rbox_out_offset, c+qh->rbox_out_offset);
|
||||
} /* qh_out3n */
|
||||
|
||||
void qh_outcoord(qhT *qh, int iscdd, double *coord, int dim) {
|
||||
double *p= coord;
|
||||
int k;
|
||||
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
for (k=0; k < dim; k++)
|
||||
qh_out1(qh, *(p++));
|
||||
qh_fprintf_rbox(qh, qh->fout, 9396, "\n");
|
||||
} /* qh_outcoord */
|
||||
|
||||
void qh_outcoincident(qhT *qh, int coincidentpoints, double radius, int iscdd, double *coord, int dim) {
|
||||
double *p;
|
||||
double randr, delta;
|
||||
int i,k;
|
||||
double randmax= qh_RANDOMmax;
|
||||
|
||||
for (i=0; i<coincidentpoints; i++) {
|
||||
p= coord;
|
||||
if (iscdd)
|
||||
qh_out1(qh, 1.0);
|
||||
for (k=0; k < dim; k++) {
|
||||
randr= qh_RANDOMint;
|
||||
delta= 2.0 * randr/randmax - 1.0; /* -1..+1 */
|
||||
delta *= radius;
|
||||
qh_out1(qh, *(p++) + delta);
|
||||
}
|
||||
qh_fprintf_rbox(qh, qh->fout, 9410, "\n");
|
||||
}
|
||||
} /* qh_outcoincident */
|
||||
|
||||
/*------------------------------------------------
|
||||
Only called from qh_rboxpoints2 or qh_fprintf_rbox
|
||||
qh_fprintf_rbox is only called from qh_rboxpoints2
|
||||
The largest exitcode is '255' for compatibility with exit()
|
||||
*/
|
||||
void qh_errexit_rbox(qhT *qh, int exitcode)
|
||||
{
|
||||
longjmp(qh->rbox_errexit, exitcode);
|
||||
} /* qh_errexit_rbox */
|
||||
|
||||
@@ -0,0 +1,727 @@
|
||||
/*<html><pre> -<a href="qh-stat_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
stat_r.c
|
||||
contains all statistics that are collected for qhull
|
||||
|
||||
see qh-stat_r.htm and stat_r.h
|
||||
|
||||
Copyright (c) 1993-2020 The Geometry Center.
|
||||
$Id: //main/2019/qhull/src/libqhull_r/stat_r.c#9 $$Change: 3037 $
|
||||
$DateTime: 2020/09/03 17:28:32 $$Author: bbarber $
|
||||
*/
|
||||
|
||||
#include "qhull_ra.h"
|
||||
|
||||
/*========== functions in alphabetic order ================*/
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="allstatA">-</a>
|
||||
|
||||
qh_allstatA()
|
||||
define statistics in groups of 20
|
||||
|
||||
notes:
|
||||
(otherwise, 'gcc -O2' uses too much memory)
|
||||
uses qhstat.next
|
||||
*/
|
||||
void qh_allstatA(qhT *qh) {
|
||||
|
||||
/* zdef_(type,name,doc,average) */
|
||||
zzdef_(zdoc, Zdoc2, "precision statistics", -1);
|
||||
zdef_(zinc, Znewvertex, NULL, -1);
|
||||
zdef_(wadd, Wnewvertex, "ave. distance of a new vertex to a facet", Znewvertex);
|
||||
zzdef_(wmax, Wnewvertexmax, "max. distance of a new vertex to a facet", -1);
|
||||
zdef_(wmax, Wvertexmax, "max. distance of an output vertex to a facet", -1);
|
||||
zdef_(wmin, Wvertexmin, "min. distance of an output vertex to a facet", -1);
|
||||
zdef_(wmin, Wmindenom, "min. denominator in hyperplane computation", -1);
|
||||
|
||||
qh->qhstat.precision= qh->qhstat.next; /* usually call qh_joggle_restart, printed if Q0 or QJn */
|
||||
zzdef_(zdoc, Zdoc3, "precision problems (corrected unless 'Q0' or an error)", -1);
|
||||
zzdef_(zinc, Zcoplanarridges, "coplanar half ridges in output", -1);
|
||||
zzdef_(zinc, Zconcaveridges, "concave half ridges in output", -1);
|
||||
zzdef_(zinc, Zflippedfacets, "flipped facets", -1);
|
||||
zzdef_(zinc, Zcoplanarhorizon, "coplanar horizon facets for new vertices", -1);
|
||||
zzdef_(zinc, Zcoplanarpart, "coplanar points during partitioning", -1);
|
||||
zzdef_(zinc, Zminnorm, "degenerate hyperplanes recomputed with gaussian elimination", -1);
|
||||
zzdef_(zinc, Znearlysingular, "nearly singular or axis-parallel hyperplanes", -1);
|
||||
zzdef_(zinc, Zback0, "zero divisors during back substitute", -1);
|
||||
zzdef_(zinc, Zgauss0, "zero divisors during gaussian elimination", -1);
|
||||
zzdef_(zinc, Zmultiridge, "dupridges with multiple neighbors", -1);
|
||||
zzdef_(zinc, Zflipridge, "dupridges with flip facet into good neighbor", -1);
|
||||
zzdef_(zinc, Zflipridge2, "dupridges with flip facet into good flip neighbor", -1);
|
||||
}
|
||||
void qh_allstatB(qhT *qh) {
|
||||
zzdef_(zdoc, Zdoc1, "summary information", -1);
|
||||
zdef_(zinc, Zvertices, "number of vertices in output", -1);
|
||||
zdef_(zinc, Znumfacets, "number of facets in output", -1);
|
||||
zdef_(zinc, Znonsimplicial, "number of non-simplicial facets in output", -1);
|
||||
zdef_(zinc, Znowsimplicial, "simplicial facets that were non-simplicial", -1);
|
||||
zdef_(zinc, Znumridges, "number of ridges in output", -1);
|
||||
zdef_(zadd, Znumridges, "average number of ridges per facet", Znumfacets);
|
||||
zdef_(zmax, Zmaxridges, "maximum number of ridges", -1);
|
||||
zdef_(zadd, Znumneighbors, "average number of neighbors per facet", Znumfacets);
|
||||
zdef_(zmax, Zmaxneighbors, "maximum number of neighbors", -1);
|
||||
zdef_(zadd, Znumvertices, "average number of vertices per facet", Znumfacets);
|
||||
zdef_(zmax, Zmaxvertices, "maximum number of vertices", -1);
|
||||
zdef_(zadd, Znumvneighbors, "average number of neighbors per vertex", Zvertices);
|
||||
zdef_(zmax, Zmaxvneighbors, "maximum number of neighbors", -1);
|
||||
zdef_(wadd, Wcpu, "cpu seconds for qhull after input", -1);
|
||||
zdef_(zinc, Ztotvertices, "vertices created altogether", -1);
|
||||
zzdef_(zinc, Zsetplane, "facets created altogether", -1);
|
||||
zdef_(zinc, Ztotridges, "ridges created altogether", -1);
|
||||
zdef_(zinc, Zpostfacets, "facets before post merge", -1);
|
||||
zdef_(zadd, Znummergetot, "average merges per facet (at most 511)", Znumfacets);
|
||||
zdef_(zmax, Znummergemax, " maximum merges for a facet (at most 511)", -1);
|
||||
zdef_(zinc, Zangle, NULL, -1);
|
||||
zdef_(wadd, Wangle, "average cosine (angle) of facet normals for all ridges", Zangle);
|
||||
zdef_(wmax, Wanglemax, " maximum cosine of facet normals (flatest) across a ridge", -1);
|
||||
zdef_(wmin, Wanglemin, " minimum cosine of facet normals (sharpest) across a ridge", -1);
|
||||
zdef_(wadd, Wareatot, "total area of facets", -1);
|
||||
zdef_(wmax, Wareamax, " maximum facet area", -1);
|
||||
zdef_(wmin, Wareamin, " minimum facet area", -1);
|
||||
}
|
||||
void qh_allstatC(qhT *qh) {
|
||||
zdef_(zdoc, Zdoc9, "build hull statistics", -1);
|
||||
zzdef_(zinc, Zprocessed, "points processed", -1);
|
||||
zzdef_(zinc, Zretry, "retries due to precision problems", -1);
|
||||
zdef_(wmax, Wretrymax, " max. random joggle", -1);
|
||||
zdef_(zmax, Zmaxvertex, "max. vertices at any one time", -1);
|
||||
zdef_(zinc, Ztotvisible, "ave. visible facets per iteration", Zprocessed);
|
||||
zdef_(zinc, Zinsidevisible, " ave. visible facets without an horizon neighbor", Zprocessed);
|
||||
zdef_(zadd, Zvisfacettot, " ave. facets deleted per iteration", Zprocessed);
|
||||
zdef_(zmax, Zvisfacetmax, " maximum", -1);
|
||||
zdef_(zadd, Zvisvertextot, "ave. visible vertices per iteration", Zprocessed);
|
||||
zdef_(zmax, Zvisvertexmax, " maximum", -1);
|
||||
zdef_(zinc, Ztothorizon, "ave. horizon facets per iteration", Zprocessed);
|
||||
zdef_(zadd, Znewfacettot, "ave. new or merged facets per iteration", Zprocessed);
|
||||
zdef_(zmax, Znewfacetmax, " maximum (includes initial simplex)", -1);
|
||||
zdef_(wadd, Wnewbalance, "average new facet balance", Zprocessed);
|
||||
zdef_(wadd, Wnewbalance2, " standard deviation", -1);
|
||||
zdef_(wadd, Wpbalance, "average partition balance", Zpbalance);
|
||||
zdef_(wadd, Wpbalance2, " standard deviation", -1);
|
||||
zdef_(zinc, Zpbalance, " count", -1);
|
||||
zdef_(zinc, Zsearchpoints, "searches of all points for initial simplex", -1);
|
||||
zdef_(zinc, Zdetfacetarea, "determinants for facet area", -1);
|
||||
zdef_(zinc, Znoarea, " determinants not computed because vertex too low", -1);
|
||||
zdef_(zinc, Zdetsimplex, "determinants for initial hull or voronoi vertices", -1);
|
||||
zdef_(zinc, Znotmax, "points ignored (!above max_outside)", -1);
|
||||
zdef_(zinc, Zpinchedapex, "points ignored (pinched apex)", -1);
|
||||
zdef_(zinc, Znotgood, "points ignored (!above a good facet)", -1);
|
||||
zdef_(zinc, Znotgoodnew, "points ignored (didn't create a good new facet)", -1);
|
||||
zdef_(zinc, Zgoodfacet, "good facets found", -1);
|
||||
zzdef_(zinc, Znumvisibility, "distance tests for facet visibility", -1);
|
||||
zdef_(zinc, Zdistvertex, "distance tests to report minimum vertex", -1);
|
||||
zzdef_(zinc, Ztotcheck, "points checked for facets' outer planes", -1);
|
||||
zzdef_(zinc, Zcheckpart, " ave. distance tests per check", Ztotcheck);
|
||||
}
|
||||
void qh_allstatD(qhT *qh) {
|
||||
zdef_(zinc, Zvisit, "resets of visit_id", -1);
|
||||
zdef_(zinc, Zvvisit, " resets of vertex_visit", -1);
|
||||
zdef_(zmax, Zvisit2max, " max visit_id/2", -1);
|
||||
zdef_(zmax, Zvvisit2max, " max vertex_visit/2", -1);
|
||||
|
||||
zdef_(zdoc, Zdoc4, "partitioning statistics (see previous for outer planes)", -1);
|
||||
zzdef_(zadd, Zdelvertextot, "total vertices deleted", -1);
|
||||
zdef_(zmax, Zdelvertexmax, " maximum vertices deleted per iteration", -1);
|
||||
zdef_(zinc, Zfindbest, "calls to findbest", -1);
|
||||
zdef_(zadd, Zfindbesttot, " ave. facets tested", Zfindbest);
|
||||
zdef_(zmax, Zfindbestmax, " max. facets tested", -1);
|
||||
zdef_(zadd, Zfindcoplanar, " ave. coplanar search", Zfindbest);
|
||||
zdef_(zinc, Zfindnew, "calls to findbestnew", -1);
|
||||
zdef_(zadd, Zfindnewtot, " ave. facets tested", Zfindnew);
|
||||
zdef_(zmax, Zfindnewmax, " max. facets tested", -1);
|
||||
zdef_(zinc, Zfindnewjump, " ave. clearly better", Zfindnew);
|
||||
zdef_(zinc, Zfindnewsharp, " calls due to qh_sharpnewfacets", -1);
|
||||
zdef_(zinc, Zfindhorizon, "calls to findhorizon", -1);
|
||||
zdef_(zadd, Zfindhorizontot, " ave. facets tested", Zfindhorizon);
|
||||
zdef_(zmax, Zfindhorizonmax, " max. facets tested", -1);
|
||||
zdef_(zinc, Zfindjump, " ave. clearly better", Zfindhorizon);
|
||||
zdef_(zinc, Znewbesthorizon, " new bestfacets during qh_findbesthorizon", -1);
|
||||
zdef_(zinc, Zpartangle, "angle tests for repartitioned coplanar points", -1);
|
||||
zdef_(zinc, Zpartcorner, " repartitioned coplanar points above a corner facet", -1);
|
||||
zdef_(zinc, Zparthidden, " repartitioned coplanar points above a hidden facet", -1);
|
||||
zdef_(zinc, Zparttwisted, " repartitioned coplanar points above a twisted facet", -1);
|
||||
}
|
||||
void qh_allstatE(qhT *qh) {
|
||||
zdef_(zinc, Zpartinside, "inside points", -1);
|
||||
zdef_(zinc, Zpartnear, " near inside points kept with a facet", -1);
|
||||
zdef_(zinc, Zcoplanarinside, " inside points that were coplanar with a facet", -1);
|
||||
zdef_(zinc, Zbestlower, "calls to findbestlower", -1);
|
||||
zdef_(zinc, Zbestlowerv, " with search of vertex neighbors", -1);
|
||||
zdef_(zinc, Zbestlowerall, " with rare search of all facets", -1);
|
||||
zdef_(zmax, Zbestloweralln, " facets per search of all facets", -1);
|
||||
zdef_(wadd, Wmaxout, "difference in max_outside at final check", -1);
|
||||
zzdef_(zinc, Zpartitionall, "distance tests for initial partition", -1);
|
||||
zdef_(zinc, Ztotpartition, "partitions of a point", -1);
|
||||
zzdef_(zinc, Zpartition, "distance tests for partitioning", -1);
|
||||
zzdef_(zinc, Zdistcheck, "distance tests for checking flipped facets", -1);
|
||||
zzdef_(zinc, Zdistconvex, "distance tests for checking convexity", -1);
|
||||
zdef_(zinc, Zdistgood, "distance tests for checking good point", -1);
|
||||
zdef_(zinc, Zdistio, "distance tests for output", -1);
|
||||
zdef_(zinc, Zdiststat, "distance tests for statistics", -1);
|
||||
zzdef_(zinc, Zdistplane, "total number of distance tests", -1);
|
||||
zdef_(zinc, Ztotpartcoplanar, "partitions of coplanar points or deleted vertices", -1);
|
||||
zzdef_(zinc, Zpartcoplanar, " distance tests for these partitions", -1);
|
||||
zdef_(zinc, Zcomputefurthest, "distance tests for computing furthest", -1);
|
||||
}
|
||||
void qh_allstatE2(qhT *qh) {
|
||||
zdef_(zdoc, Zdoc5, "statistics for matching ridges", -1);
|
||||
zdef_(zinc, Zhashlookup, "total lookups for matching ridges of new facets", -1);
|
||||
zdef_(zinc, Zhashtests, "average number of tests to match a ridge", Zhashlookup);
|
||||
zdef_(zinc, Zhashridge, "total lookups of subridges (duplicates and boundary)", -1);
|
||||
zdef_(zinc, Zhashridgetest, "average number of tests per subridge", Zhashridge);
|
||||
zdef_(zinc, Zdupsame, "duplicated ridges in same merge cycle", -1);
|
||||
zdef_(zinc, Zdupflip, "duplicated ridges with flipped facets", -1);
|
||||
|
||||
zdef_(zdoc, Zdoc6, "statistics for determining merges", -1);
|
||||
zdef_(zinc, Zangletests, "angles computed for ridge convexity", -1);
|
||||
zdef_(zinc, Zbestcentrum, "best merges used centrum instead of vertices",-1);
|
||||
zzdef_(zinc, Zbestdist, "distance tests for best merge", -1);
|
||||
zzdef_(zinc, Zcentrumtests, "distance tests for centrum convexity", -1);
|
||||
zzdef_(zinc, Zvertextests, "distance tests for vertex convexity", -1);
|
||||
zzdef_(zinc, Zdistzero, "distance tests for checking simplicial convexity", -1);
|
||||
zdef_(zinc, Zcoplanarangle, "coplanar angles in getmergeset", -1);
|
||||
zdef_(zinc, Zcoplanarcentrum, "coplanar centrums or vertices in getmergeset", -1);
|
||||
zdef_(zinc, Zconcaveridge, "concave ridges in getmergeset", -1);
|
||||
zdef_(zinc, Zconcavecoplanarridge, "concave-coplanar ridges in getmergeset", -1);
|
||||
zdef_(zinc, Ztwistedridge, "twisted ridges in getmergeset", -1);
|
||||
}
|
||||
void qh_allstatF(qhT *qh) {
|
||||
zdef_(zdoc, Zdoc7, "statistics for merging", -1);
|
||||
zdef_(zinc, Zpremergetot, "merge iterations", -1);
|
||||
zdef_(zadd, Zmergeinittot, "ave. initial non-convex ridges per iteration", Zpremergetot);
|
||||
zdef_(zadd, Zmergeinitmax, " maximum", -1);
|
||||
zdef_(zadd, Zmergesettot, " ave. additional non-convex ridges per iteration", Zpremergetot);
|
||||
zdef_(zadd, Zmergesetmax, " maximum additional in one pass", -1);
|
||||
zdef_(zadd, Zmergeinittot2, "initial non-convex ridges for post merging", -1);
|
||||
zdef_(zadd, Zmergesettot2, " additional non-convex ridges", -1);
|
||||
zdef_(wmax, Wmaxoutside, "max distance of vertex or coplanar point above facet (w/roundoff)", -1);
|
||||
zdef_(wmin, Wminvertex, "max distance of vertex below facet (or roundoff)", -1);
|
||||
zdef_(zinc, Zwidefacet, "centrums frozen due to a wide merge", -1);
|
||||
zdef_(zinc, Zwidevertices, "centrums frozen due to extra vertices", -1);
|
||||
zzdef_(zinc, Ztotmerge, "total number of facets or cycles of facets merged", -1);
|
||||
zdef_(zinc, Zmergesimplex, "merged a simplex", -1);
|
||||
zdef_(zinc, Zonehorizon, "simplices merged into coplanar horizon", -1);
|
||||
zzdef_(zinc, Zcyclehorizon, "cycles of facets merged into coplanar horizon", -1);
|
||||
zzdef_(zadd, Zcyclefacettot, " ave. facets per cycle", Zcyclehorizon);
|
||||
zdef_(zmax, Zcyclefacetmax, " max. facets", -1);
|
||||
zdef_(zinc, Zmergeintocoplanar, "new facets merged into coplanar horizon", -1);
|
||||
zdef_(zinc, Zmergeintohorizon, "new facets merged into horizon", -1);
|
||||
zdef_(zinc, Zmergenew, "new facets merged", -1);
|
||||
zdef_(zinc, Zmergehorizon, "horizon facets merged into new facets", -1);
|
||||
zdef_(zinc, Zmergevertex, "vertices deleted by merging", -1);
|
||||
zdef_(zinc, Zcyclevertex, "vertices deleted by merging into coplanar horizon", -1);
|
||||
zdef_(zinc, Zdegenvertex, "vertices deleted by degenerate facet", -1);
|
||||
zdef_(zinc, Zmergeflipdup, "merges due to flipped facets in duplicated ridge", -1);
|
||||
zdef_(zinc, Zredundant, "merges due to redundant neighbors", -1);
|
||||
zdef_(zinc, Zredundantmerge, " detected by qh_test_nonsimplicial_merge instead of qh_test_redundant_neighbors", -1);
|
||||
zdef_(zadd, Ztestvneighbor, "non-convex vertex neighbors", -1);
|
||||
}
|
||||
void qh_allstatG(qhT *qh) {
|
||||
zdef_(zinc, Zacoplanar, "merges due to angle coplanar facets", -1);
|
||||
zdef_(wadd, Wacoplanartot, " average merge distance", Zacoplanar);
|
||||
zdef_(wmax, Wacoplanarmax, " maximum merge distance", -1);
|
||||
zdef_(zinc, Zcoplanar, "merges due to coplanar facets", -1);
|
||||
zdef_(wadd, Wcoplanartot, " average merge distance", Zcoplanar);
|
||||
zdef_(wmax, Wcoplanarmax, " maximum merge distance", -1);
|
||||
zdef_(zinc, Zconcave, "merges due to concave facets", -1);
|
||||
zdef_(wadd, Wconcavetot, " average merge distance", Zconcave);
|
||||
zdef_(wmax, Wconcavemax, " maximum merge distance", -1);
|
||||
zdef_(zinc, Zconcavecoplanar, "merges due to concave-coplanar facets", -1);
|
||||
zdef_(wadd, Wconcavecoplanartot, " average merge distance", Zconcavecoplanar);
|
||||
zdef_(wmax, Wconcavecoplanarmax, " maximum merge distance", -1);
|
||||
zdef_(zinc, Zavoidold, "coplanar/concave merges due to avoiding old merge", -1);
|
||||
zdef_(wadd, Wavoidoldtot, " average merge distance", Zavoidold);
|
||||
zdef_(wmax, Wavoidoldmax, " maximum merge distance", -1);
|
||||
zdef_(zinc, Zdegen, "merges due to degenerate facets", -1);
|
||||
zdef_(wadd, Wdegentot, " average merge distance", Zdegen);
|
||||
zdef_(wmax, Wdegenmax, " maximum merge distance", -1);
|
||||
zdef_(zinc, Zflipped, "merges due to removing flipped facets", -1);
|
||||
zdef_(wadd, Wflippedtot, " average merge distance", Zflipped);
|
||||
zdef_(wmax, Wflippedmax, " maximum merge distance", -1);
|
||||
zdef_(zinc, Zduplicate, "merges due to dupridges", -1);
|
||||
zdef_(wadd, Wduplicatetot, " average merge distance", Zduplicate);
|
||||
zdef_(wmax, Wduplicatemax, " maximum merge distance", -1);
|
||||
zdef_(zinc, Ztwisted, "merges due to twisted facets", -1);
|
||||
zdef_(wadd, Wtwistedtot, " average merge distance", Ztwisted);
|
||||
zdef_(wmax, Wtwistedmax, " maximum merge distance", -1);
|
||||
}
|
||||
void qh_allstatH(qhT *qh) {
|
||||
zdef_(zdoc, Zdoc8, "statistics for vertex merges", -1);
|
||||
zzdef_(zinc, Zpinchduplicate, "merge pinched vertices for a duplicate ridge", -1);
|
||||
zzdef_(zinc, Zpinchedvertex, "merge pinched vertices for a dupridge", -1);
|
||||
zdef_(zinc, Zrenameshare, "renamed vertices shared by two facets", -1);
|
||||
zdef_(zinc, Zrenamepinch, "renamed vertices in a pinched facet", -1);
|
||||
zdef_(zinc, Zrenameall, "renamed vertices shared by multiple facets", -1);
|
||||
zdef_(zinc, Zfindfail, "rename failures due to duplicated ridges", -1);
|
||||
zdef_(zinc, Znewvertexridge, " found new vertex in ridge", -1);
|
||||
zdef_(zinc, Zdelridge, "deleted ridges due to renamed vertices", -1);
|
||||
zdef_(zinc, Zdropneighbor, "dropped neighbors due to renamed vertices", -1);
|
||||
zdef_(zinc, Zdropdegen, "merge degenerate facets due to dropped neighbors", -1);
|
||||
zdef_(zinc, Zdelfacetdup, " facets deleted because of no neighbors", -1);
|
||||
zdef_(zinc, Zremvertex, "vertices removed from facets due to no ridges", -1);
|
||||
zdef_(zinc, Zremvertexdel, " deleted", -1);
|
||||
zdef_(zinc, Zretryadd, "retry qh_addpoint after merge pinched vertex", -1);
|
||||
zdef_(zadd, Zretryaddtot, " tot. merge pinched vertex due to dupridge", -1);
|
||||
zdef_(zmax, Zretryaddmax, " max. merge pinched vertex for a qh_addpoint", -1);
|
||||
zdef_(zinc, Zintersectnum, "vertex intersections for locating redundant vertices", -1);
|
||||
zdef_(zinc, Zintersectfail, "intersections failed to find a redundant vertex", -1);
|
||||
zdef_(zinc, Zintersect, "intersections found redundant vertices", -1);
|
||||
zdef_(zadd, Zintersecttot, " ave. number found per vertex", Zintersect);
|
||||
zdef_(zmax, Zintersectmax, " max. found for a vertex", -1);
|
||||
zdef_(zinc, Zvertexridge, NULL, -1);
|
||||
zdef_(zadd, Zvertexridgetot, " ave. number of ridges per tested vertex", Zvertexridge);
|
||||
zdef_(zmax, Zvertexridgemax, " max. number of ridges per tested vertex", -1);
|
||||
|
||||
zdef_(zdoc, Zdoc10, "memory usage statistics (in bytes)", -1);
|
||||
zdef_(zadd, Zmemfacets, "for facets and their normals, neighbor and vertex sets", -1);
|
||||
zdef_(zadd, Zmemvertices, "for vertices and their neighbor sets", -1);
|
||||
zdef_(zadd, Zmempoints, "for input points, outside and coplanar sets, and qhT",-1);
|
||||
zdef_(zadd, Zmemridges, "for ridges and their vertex sets", -1);
|
||||
} /* allstat */
|
||||
|
||||
void qh_allstatI(qhT *qh) {
|
||||
qh->qhstat.vridges= qh->qhstat.next; /* printed in qh_produce_output2 if non-zero Zridge or Zridgemid */
|
||||
zzdef_(zdoc, Zdoc11, "Voronoi ridge statistics", -1);
|
||||
zzdef_(zinc, Zridge, "non-simplicial Voronoi vertices for all ridges", -1);
|
||||
zzdef_(wadd, Wridge, " ave. distance to ridge", Zridge);
|
||||
zzdef_(wmax, Wridgemax, " max. distance to ridge", -1);
|
||||
zzdef_(zinc, Zridgemid, "bounded ridges", -1);
|
||||
zzdef_(wadd, Wridgemid, " ave. distance of midpoint to ridge", Zridgemid);
|
||||
zzdef_(wmax, Wridgemidmax, " max. distance of midpoint to ridge", -1);
|
||||
zzdef_(zinc, Zridgeok, "bounded ridges with ok normal", -1);
|
||||
zzdef_(wadd, Wridgeok, " ave. angle to ridge", Zridgeok);
|
||||
zzdef_(wmax, Wridgeokmax, " max. angle to ridge", -1);
|
||||
zzdef_(zinc, Zridge0, "bounded ridges with near-zero normal", -1);
|
||||
zzdef_(wadd, Wridge0, " ave. angle to ridge", Zridge0);
|
||||
zzdef_(wmax, Wridge0max, " max. angle to ridge", -1);
|
||||
|
||||
zdef_(zdoc, Zdoc12, "Triangulation statistics ('Qt')", -1);
|
||||
zdef_(zinc, Ztricoplanar, "non-simplicial facets triangulated", -1);
|
||||
zdef_(zadd, Ztricoplanartot, " ave. new facets created (may be deleted)", Ztricoplanar);
|
||||
zdef_(zmax, Ztricoplanarmax, " max. new facets created", -1);
|
||||
zdef_(zinc, Ztrinull, "null new facets deleted (duplicated vertex)", -1);
|
||||
zdef_(zinc, Ztrimirror, "mirrored pairs of new facets deleted (same vertices)", -1);
|
||||
zdef_(zinc, Ztridegen, "degenerate new facets in output (same ridge)", -1);
|
||||
} /* allstat */
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="allstatistics">-</a>
|
||||
|
||||
qh_allstatistics()
|
||||
reset printed flag for all statistics
|
||||
*/
|
||||
void qh_allstatistics(qhT *qh) {
|
||||
int i;
|
||||
|
||||
for(i=ZEND; i--; )
|
||||
qh->qhstat.printed[i]= False;
|
||||
} /* allstatistics */
|
||||
|
||||
#if qh_KEEPstatistics
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="collectstatistics">-</a>
|
||||
|
||||
qh_collectstatistics()
|
||||
collect statistics for qh.facet_list
|
||||
|
||||
*/
|
||||
void qh_collectstatistics(qhT *qh) {
|
||||
facetT *facet, *neighbor, **neighborp;
|
||||
vertexT *vertex, **vertexp;
|
||||
realT dotproduct, dist;
|
||||
int sizneighbors, sizridges, sizvertices, i;
|
||||
|
||||
qh->old_randomdist= qh->RANDOMdist;
|
||||
qh->RANDOMdist= False;
|
||||
zval_(Zmempoints)= qh->num_points * qh->normal_size + (int)sizeof(qhT);
|
||||
zval_(Zmemfacets)= 0;
|
||||
zval_(Zmemridges)= 0;
|
||||
zval_(Zmemvertices)= 0;
|
||||
zval_(Zangle)= 0;
|
||||
wval_(Wangle)= 0.0;
|
||||
zval_(Znumridges)= 0;
|
||||
zval_(Znumfacets)= 0;
|
||||
zval_(Znumneighbors)= 0;
|
||||
zval_(Znumvertices)= 0;
|
||||
zval_(Znumvneighbors)= 0;
|
||||
zval_(Znummergetot)= 0;
|
||||
zval_(Znummergemax)= 0;
|
||||
zval_(Zvertices)= qh->num_vertices - qh_setsize(qh, qh->del_vertices);
|
||||
if (qh->MERGING || qh->APPROXhull || qh->JOGGLEmax < REALmax/2)
|
||||
wmax_(Wmaxoutside, qh->max_outside);
|
||||
if (qh->MERGING)
|
||||
wmin_(Wminvertex, qh->min_vertex);
|
||||
if (!qh_checklists(qh, qh->facet_list)) {
|
||||
qh_fprintf(qh, qh->ferr, 6373, "qhull internal error: qh_checklists failed on qh_collectstatistics\n");
|
||||
if (!qh->ERREXITcalled)
|
||||
qh_errexit(qh, qh_ERRqhull, NULL, NULL);
|
||||
}
|
||||
FORALLfacets
|
||||
facet->seen= False;
|
||||
if (qh->DELAUNAY) {
|
||||
FORALLfacets {
|
||||
if (facet->upperdelaunay != qh->UPPERdelaunay)
|
||||
facet->seen= True; /* remove from angle statistics */
|
||||
}
|
||||
}
|
||||
FORALLfacets {
|
||||
if (facet->visible && qh->NEWfacets)
|
||||
continue;
|
||||
sizvertices= qh_setsize(qh, facet->vertices);
|
||||
sizneighbors= qh_setsize(qh, facet->neighbors);
|
||||
sizridges= qh_setsize(qh, facet->ridges);
|
||||
zinc_(Znumfacets);
|
||||
zadd_(Znumvertices, sizvertices);
|
||||
zmax_(Zmaxvertices, sizvertices);
|
||||
zadd_(Znumneighbors, sizneighbors);
|
||||
zmax_(Zmaxneighbors, sizneighbors);
|
||||
zadd_(Znummergetot, facet->nummerge);
|
||||
i= facet->nummerge; /* avoid warnings */
|
||||
zmax_(Znummergemax, i);
|
||||
if (!facet->simplicial) {
|
||||
if (sizvertices == qh->hull_dim) {
|
||||
zinc_(Znowsimplicial);
|
||||
}else {
|
||||
zinc_(Znonsimplicial);
|
||||
}
|
||||
}
|
||||
if (sizridges) {
|
||||
zadd_(Znumridges, sizridges);
|
||||
zmax_(Zmaxridges, sizridges);
|
||||
}
|
||||
zadd_(Zmemfacets, (int)sizeof(facetT) + qh->normal_size + 2*SETbasesize
|
||||
+ SETelemsize * (sizneighbors + sizvertices));
|
||||
if (facet->ridges) {
|
||||
zadd_(Zmemridges,
|
||||
SETbasesize + SETelemsize * sizridges + sizridges *
|
||||
((int)sizeof(ridgeT) + SETbasesize + SETelemsize * (qh->hull_dim-1))/2);
|
||||
}
|
||||
if (facet->outsideset)
|
||||
zadd_(Zmempoints, SETbasesize + SETelemsize * qh_setsize(qh, facet->outsideset));
|
||||
if (facet->coplanarset)
|
||||
zadd_(Zmempoints, SETbasesize + SETelemsize * qh_setsize(qh, facet->coplanarset));
|
||||
if (facet->seen) /* Delaunay upper envelope */
|
||||
continue;
|
||||
facet->seen= True;
|
||||
FOREACHneighbor_(facet) {
|
||||
if (neighbor == qh_DUPLICATEridge || neighbor == qh_MERGEridge
|
||||
|| neighbor->seen || !facet->normal || !neighbor->normal)
|
||||
continue;
|
||||
dotproduct= qh_getangle(qh, facet->normal, neighbor->normal);
|
||||
zinc_(Zangle);
|
||||
wadd_(Wangle, dotproduct);
|
||||
wmax_(Wanglemax, dotproduct)
|
||||
wmin_(Wanglemin, dotproduct)
|
||||
}
|
||||
if (facet->normal) {
|
||||
FOREACHvertex_(facet->vertices) {
|
||||
zinc_(Zdiststat);
|
||||
qh_distplane(qh, vertex->point, facet, &dist);
|
||||
wmax_(Wvertexmax, dist);
|
||||
wmin_(Wvertexmin, dist);
|
||||
}
|
||||
}
|
||||
}
|
||||
FORALLvertices {
|
||||
if (vertex->deleted)
|
||||
continue;
|
||||
zadd_(Zmemvertices, (int)sizeof(vertexT));
|
||||
if (vertex->neighbors) {
|
||||
sizneighbors= qh_setsize(qh, vertex->neighbors);
|
||||
zadd_(Znumvneighbors, sizneighbors);
|
||||
zmax_(Zmaxvneighbors, sizneighbors);
|
||||
zadd_(Zmemvertices, (int)sizeof(vertexT) + SETelemsize * sizneighbors);
|
||||
}
|
||||
}
|
||||
qh->RANDOMdist= qh->old_randomdist;
|
||||
} /* collectstatistics */
|
||||
#endif /* qh_KEEPstatistics */
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="initstatistics">-</a>
|
||||
|
||||
qh_initstatistics(qh)
|
||||
initialize statistics
|
||||
|
||||
notes:
|
||||
NOerrors -- qh_initstatistics can not use qh_errexit(), qh_fprintf, or qh.ferr
|
||||
On first call, only qhmem.ferr is defined. qh_memalloc is not setup.
|
||||
Also invoked by QhullQh().
|
||||
*/
|
||||
void qh_initstatistics(qhT *qh) {
|
||||
int i;
|
||||
realT realx;
|
||||
int intx;
|
||||
|
||||
qh_allstatistics(qh);
|
||||
qh->qhstat.next= 0;
|
||||
qh_allstatA(qh);
|
||||
qh_allstatB(qh);
|
||||
qh_allstatC(qh);
|
||||
qh_allstatD(qh);
|
||||
qh_allstatE(qh);
|
||||
qh_allstatE2(qh);
|
||||
qh_allstatF(qh);
|
||||
qh_allstatG(qh);
|
||||
qh_allstatH(qh);
|
||||
qh_allstatI(qh);
|
||||
if (qh->qhstat.next > (int)sizeof(qh->qhstat.id)) {
|
||||
qh_fprintf_stderr(6184, "qhull internal error (qh_initstatistics): increase size of qhstat.id[]. qhstat.next %d should be <= sizeof(qh->qhstat.id) %d\n",
|
||||
qh->qhstat.next, (int)sizeof(qh->qhstat.id));
|
||||
#if 0 /* for locating error, Znumridges should be duplicated */
|
||||
for(i=0; i < ZEND; i++) {
|
||||
int j;
|
||||
for(j=i+1; j < ZEND; j++) {
|
||||
if (qh->qhstat.id[i] == qh->qhstat.id[j]) {
|
||||
qh_fprintf_stderr(6185, "qhull error (qh_initstatistics): duplicated statistic %d at indices %d and %d\n",
|
||||
qh->qhstat.id[i], i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
qh_exit(qh_ERRqhull); /* can not use qh_errexit() */
|
||||
}
|
||||
qh->qhstat.init[zinc].i= 0;
|
||||
qh->qhstat.init[zadd].i= 0;
|
||||
qh->qhstat.init[zmin].i= INT_MAX;
|
||||
qh->qhstat.init[zmax].i= INT_MIN;
|
||||
qh->qhstat.init[wadd].r= 0;
|
||||
qh->qhstat.init[wmin].r= REALmax;
|
||||
qh->qhstat.init[wmax].r= -REALmax;
|
||||
for(i=0; i < ZEND; i++) {
|
||||
if (qh->qhstat.type[i] > ZTYPEreal) {
|
||||
realx= qh->qhstat.init[(unsigned char)(qh->qhstat.type[i])].r;
|
||||
qh->qhstat.stats[i].r= realx;
|
||||
}else if (qh->qhstat.type[i] != zdoc) {
|
||||
intx= qh->qhstat.init[(unsigned char)(qh->qhstat.type[i])].i;
|
||||
qh->qhstat.stats[i].i= intx;
|
||||
}
|
||||
}
|
||||
} /* initstatistics */
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="newstats">-</a>
|
||||
|
||||
qh_newstats(qh )
|
||||
returns True if statistics for zdoc
|
||||
|
||||
returns:
|
||||
next zdoc
|
||||
*/
|
||||
boolT qh_newstats(qhT *qh, int idx, int *nextindex) {
|
||||
boolT isnew= False;
|
||||
int start, i;
|
||||
|
||||
if (qh->qhstat.type[qh->qhstat.id[idx]] == zdoc)
|
||||
start= idx+1;
|
||||
else
|
||||
start= idx;
|
||||
for(i= start; i < qh->qhstat.next && qh->qhstat.type[qh->qhstat.id[i]] != zdoc; i++) {
|
||||
if (!qh_nostatistic(qh, qh->qhstat.id[i]) && !qh->qhstat.printed[qh->qhstat.id[i]])
|
||||
isnew= True;
|
||||
}
|
||||
*nextindex= i;
|
||||
return isnew;
|
||||
} /* newstats */
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="nostatistic">-</a>
|
||||
|
||||
qh_nostatistic(qh, index )
|
||||
true if no statistic to print
|
||||
*/
|
||||
boolT qh_nostatistic(qhT *qh, int i) {
|
||||
|
||||
if ((qh->qhstat.type[i] > ZTYPEreal
|
||||
&&qh->qhstat.stats[i].r == qh->qhstat.init[(unsigned char)(qh->qhstat.type[i])].r)
|
||||
|| (qh->qhstat.type[i] < ZTYPEreal
|
||||
&&qh->qhstat.stats[i].i == qh->qhstat.init[(unsigned char)(qh->qhstat.type[i])].i))
|
||||
return True;
|
||||
return False;
|
||||
} /* nostatistic */
|
||||
|
||||
#if qh_KEEPstatistics
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="printallstatistics">-</a>
|
||||
|
||||
qh_printallstatistics(qh, fp, string )
|
||||
print all statistics with header 'string'
|
||||
*/
|
||||
void qh_printallstatistics(qhT *qh, FILE *fp, const char *string) {
|
||||
|
||||
qh_allstatistics(qh);
|
||||
qh_collectstatistics(qh);
|
||||
qh_printstatistics(qh, fp, string);
|
||||
qh_memstatistics(qh, fp);
|
||||
}
|
||||
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="printstatistics">-</a>
|
||||
|
||||
qh_printstatistics(qh, fp, string )
|
||||
print statistics to a file with header 'string'
|
||||
skips statistics with qhstat.printed[] (reset with qh_allstatistics)
|
||||
|
||||
see:
|
||||
qh_printallstatistics()
|
||||
*/
|
||||
void qh_printstatistics(qhT *qh, FILE *fp, const char *string) {
|
||||
int i, k;
|
||||
realT ave; /* ignored */
|
||||
|
||||
if (qh->num_points != qh->num_vertices || zval_(Zpbalance) == 0) {
|
||||
wval_(Wpbalance)= 0.0;
|
||||
wval_(Wpbalance2)= 0.0;
|
||||
}else
|
||||
wval_(Wpbalance2)= qh_stddev(qh, zval_(Zpbalance), wval_(Wpbalance),
|
||||
wval_(Wpbalance2), &ave);
|
||||
if (zval_(Zprocessed) == 0)
|
||||
wval_(Wnewbalance2)= 0.0;
|
||||
else
|
||||
wval_(Wnewbalance2)= qh_stddev(qh, zval_(Zprocessed), wval_(Wnewbalance),
|
||||
wval_(Wnewbalance2), &ave);
|
||||
qh_fprintf(qh, fp, 9350, "\n\
|
||||
%s\n\
|
||||
qhull invoked by: %s | %s\n %s with options:\n%s\n",
|
||||
string, qh->rbox_command, qh->qhull_command, qh_version, qh->qhull_options);
|
||||
|
||||
qh_fprintf(qh, fp, 9351, "\nprecision constants:\n\
|
||||
%6.2g max. abs. coordinate in the (transformed) input ('Qbd:n')\n\
|
||||
%6.2g max. roundoff error for distance computation ('En')\n\
|
||||
%6.2g max. roundoff error for angle computations\n\
|
||||
%6.2g min. distance for outside points ('Wn')\n\
|
||||
%6.2g min. distance for visible facets ('Vn')\n\
|
||||
%6.2g max. distance for coplanar facets ('Un')\n\
|
||||
%6.2g max. facet width for recomputing centrum and area\n\
|
||||
",
|
||||
qh->MAXabs_coord, qh->DISTround, qh->ANGLEround, qh->MINoutside,
|
||||
qh->MINvisible, qh->MAXcoplanar, qh->WIDEfacet);
|
||||
if (qh->KEEPnearinside)
|
||||
qh_fprintf(qh, fp, 9352, "\
|
||||
%6.2g max. distance for near-inside points\n", qh->NEARinside);
|
||||
if (qh->premerge_cos < REALmax/2) qh_fprintf(qh, fp, 9353, "\
|
||||
%6.2g max. cosine for pre-merge angle\n", qh->premerge_cos);
|
||||
if (qh->PREmerge) qh_fprintf(qh, fp, 9354, "\
|
||||
%6.2g radius of pre-merge centrum\n", qh->premerge_centrum);
|
||||
if (qh->postmerge_cos < REALmax/2) qh_fprintf(qh, fp, 9355, "\
|
||||
%6.2g max. cosine for post-merge angle\n", qh->postmerge_cos);
|
||||
if (qh->POSTmerge) qh_fprintf(qh, fp, 9356, "\
|
||||
%6.2g radius of post-merge centrum\n", qh->postmerge_centrum);
|
||||
qh_fprintf(qh, fp, 9357, "\
|
||||
%6.2g max. distance for merging two simplicial facets\n\
|
||||
%6.2g max. roundoff error for arithmetic operations\n\
|
||||
%6.2g min. denominator for division\n\
|
||||
zero diagonal for Gauss: ", qh->ONEmerge, REALepsilon, qh->MINdenom);
|
||||
for(k=0; k < qh->hull_dim; k++)
|
||||
qh_fprintf(qh, fp, 9358, "%6.2e ", qh->NEARzero[k]);
|
||||
qh_fprintf(qh, fp, 9359, "\n\n");
|
||||
for(i=0 ; i < qh->qhstat.next; )
|
||||
qh_printstats(qh, fp, i, &i);
|
||||
} /* printstatistics */
|
||||
#endif /* qh_KEEPstatistics */
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="printstatlevel">-</a>
|
||||
|
||||
qh_printstatlevel(qh, fp, id )
|
||||
print level information for a statistic
|
||||
|
||||
notes:
|
||||
nop if id >= ZEND, printed, or same as initial value
|
||||
*/
|
||||
void qh_printstatlevel(qhT *qh, FILE *fp, int id) {
|
||||
|
||||
if (id >= ZEND || qh->qhstat.printed[id])
|
||||
return;
|
||||
if (qh->qhstat.type[id] == zdoc) {
|
||||
qh_fprintf(qh, fp, 9360, "%s\n", qh->qhstat.doc[id]);
|
||||
return;
|
||||
}
|
||||
if (qh_nostatistic(qh, id) || !qh->qhstat.doc[id])
|
||||
return;
|
||||
qh->qhstat.printed[id]= True;
|
||||
if (qh->qhstat.count[id] != -1
|
||||
&& qh->qhstat.stats[(unsigned char)(qh->qhstat.count[id])].i == 0)
|
||||
qh_fprintf(qh, fp, 9361, " *0 cnt*");
|
||||
else if (qh->qhstat.type[id] >= ZTYPEreal && qh->qhstat.count[id] == -1)
|
||||
qh_fprintf(qh, fp, 9362, "%7.2g", qh->qhstat.stats[id].r);
|
||||
else if (qh->qhstat.type[id] >= ZTYPEreal && qh->qhstat.count[id] != -1)
|
||||
qh_fprintf(qh, fp, 9363, "%7.2g", qh->qhstat.stats[id].r/ qh->qhstat.stats[(unsigned char)(qh->qhstat.count[id])].i);
|
||||
else if (qh->qhstat.type[id] < ZTYPEreal && qh->qhstat.count[id] == -1)
|
||||
qh_fprintf(qh, fp, 9364, "%7d", qh->qhstat.stats[id].i);
|
||||
else if (qh->qhstat.type[id] < ZTYPEreal && qh->qhstat.count[id] != -1)
|
||||
qh_fprintf(qh, fp, 9365, "%7.3g", (realT) qh->qhstat.stats[id].i / qh->qhstat.stats[(unsigned char)(qh->qhstat.count[id])].i);
|
||||
qh_fprintf(qh, fp, 9366, " %s\n", qh->qhstat.doc[id]);
|
||||
} /* printstatlevel */
|
||||
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="printstats">-</a>
|
||||
|
||||
qh_printstats(qh, fp, index, nextindex )
|
||||
print statistics for a zdoc group
|
||||
|
||||
returns:
|
||||
next zdoc if non-null
|
||||
*/
|
||||
void qh_printstats(qhT *qh, FILE *fp, int idx, int *nextindex) {
|
||||
int j, nexti;
|
||||
|
||||
if (qh_newstats(qh, idx, &nexti)) {
|
||||
qh_fprintf(qh, fp, 9367, "\n");
|
||||
for (j=idx; j<nexti; j++)
|
||||
qh_printstatlevel(qh, fp, qh->qhstat.id[j]);
|
||||
}
|
||||
if (nextindex)
|
||||
*nextindex= nexti;
|
||||
} /* printstats */
|
||||
|
||||
#if qh_KEEPstatistics
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="stddev">-</a>
|
||||
|
||||
qh_stddev(qh, num, tot, tot2, ave )
|
||||
compute the standard deviation and average from statistics
|
||||
|
||||
tot2 is the sum of the squares
|
||||
notes:
|
||||
computes r.m.s.:
|
||||
(x-ave)^2
|
||||
== x^2 - 2x tot/num + (tot/num)^2
|
||||
== tot2 - 2 tot tot/num + tot tot/num
|
||||
== tot2 - tot ave
|
||||
*/
|
||||
realT qh_stddev(qhT *qh, int num, realT tot, realT tot2, realT *ave) {
|
||||
realT stddev;
|
||||
|
||||
if (num <= 0) {
|
||||
qh_fprintf(qh, qh->ferr, 7101, "qhull warning (qh_stddev): expecting num > 0. Got num %d, tot %4.4g, tot2 %4.4g. Returning 0.0\n",
|
||||
num, tot, tot2);
|
||||
return 0.0;
|
||||
}
|
||||
*ave= tot/num;
|
||||
stddev= sqrt(fabs(tot2/num - *ave * *ave));
|
||||
return stddev;
|
||||
} /* stddev */
|
||||
#else
|
||||
realT qh_stddev(qhT *qh, int num, realT tot, realT tot2, realT *ave) { /* for qhull_r-exports.def */
|
||||
QHULL_UNUSED(qh)
|
||||
QHULL_UNUSED(num)
|
||||
QHULL_UNUSED(tot)
|
||||
QHULL_UNUSED(tot2)
|
||||
QHULL_UNUSED(ave)
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
#endif /* qh_KEEPstatistics */
|
||||
|
||||
#if !qh_KEEPstatistics
|
||||
void qh_collectstatistics(qhT *qh) {}
|
||||
void qh_printallstatistics(qhT *qh, FILE *fp, const char *string) {}
|
||||
void qh_printstatistics(qhT *qh, FILE *fp, const char *string) {}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,563 @@
|
||||
/*<html><pre> -<a href="qh-stat_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
stat_r.h
|
||||
contains all statistics that are collected for qhull
|
||||
|
||||
see qh-stat_r.htm and stat_r.c
|
||||
|
||||
Copyright (c) 1993-2020 The Geometry Center.
|
||||
$Id: //main/2019/qhull/src/libqhull_r/stat_r.h#4 $$Change: 2953 $
|
||||
$DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
|
||||
|
||||
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
|
||||
|
||||
/* Depends on realT. Do not include "libqhull_r" to avoid circular dependency */
|
||||
|
||||
#ifndef DEFqhT
|
||||
#define DEFqhT 1
|
||||
typedef struct qhT qhT; /* Defined by libqhull_r.h */
|
||||
#endif
|
||||
|
||||
#ifndef DEFqhstatT
|
||||
#define DEFqhstatT 1
|
||||
typedef struct qhstatT qhstatT; /* Defined here */
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="KEEPstatistics">-</a>
|
||||
|
||||
qh_KEEPstatistics
|
||||
0 turns off statistic reporting and gathering (except zzdef/zzinc/zzadd/zzval/wwval)
|
||||
|
||||
set qh_KEEPstatistics in user_r.h to 0 to turn off statistics
|
||||
*/
|
||||
#ifndef qh_KEEPstatistics
|
||||
#define qh_KEEPstatistics 1
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>-------------------------------</a><a name="statistics">-</a>
|
||||
|
||||
Zxxx for integers, Wxxx for reals
|
||||
|
||||
notes:
|
||||
be sure that all statistics are defined in stat_r.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 qh_statistics { /* alphabetical after Z/W */
|
||||
Zacoplanar,
|
||||
Wacoplanarmax,
|
||||
Wacoplanartot,
|
||||
Zangle,
|
||||
Wangle,
|
||||
Wanglemax,
|
||||
Wanglemin,
|
||||
Zangletests,
|
||||
Wareatot,
|
||||
Wareamax,
|
||||
Wareamin,
|
||||
Zavoidold,
|
||||
Wavoidoldmax,
|
||||
Wavoidoldtot,
|
||||
Zback0,
|
||||
Zbestcentrum,
|
||||
Zbestdist,
|
||||
Zbestlower,
|
||||
Zbestlowerall,
|
||||
Zbestloweralln,
|
||||
Zbestlowerv,
|
||||
Zcentrumtests,
|
||||
Zcheckpart,
|
||||
Zcomputefurthest,
|
||||
Zconcave,
|
||||
Wconcavemax,
|
||||
Wconcavetot,
|
||||
Zconcavecoplanar,
|
||||
Wconcavecoplanarmax,
|
||||
Wconcavecoplanartot,
|
||||
Zconcavecoplanarridge,
|
||||
Zconcaveridge,
|
||||
Zconcaveridges,
|
||||
Zcoplanar,
|
||||
Wcoplanarmax,
|
||||
Wcoplanartot,
|
||||
Zcoplanarangle,
|
||||
Zcoplanarcentrum,
|
||||
Zcoplanarhorizon,
|
||||
Zcoplanarinside,
|
||||
Zcoplanarpart,
|
||||
Zcoplanarridges,
|
||||
Wcpu,
|
||||
Zcyclefacetmax,
|
||||
Zcyclefacettot,
|
||||
Zcyclehorizon,
|
||||
Zcyclevertex,
|
||||
Zdegen,
|
||||
Wdegenmax,
|
||||
Wdegentot,
|
||||
Zdegenvertex,
|
||||
Zdelfacetdup,
|
||||
Zdelridge,
|
||||
Zdelvertextot,
|
||||
Zdelvertexmax,
|
||||
Zdetfacetarea,
|
||||
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,
|
||||
Zdupsame,
|
||||
Zflipped,
|
||||
Wflippedmax,
|
||||
Wflippedtot,
|
||||
Zflippedfacets,
|
||||
Zflipridge,
|
||||
Zflipridge2,
|
||||
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,
|
||||
Zmergeintocoplanar,
|
||||
Zmergeintohorizon,
|
||||
Zmergenew,
|
||||
Zmergesettot,
|
||||
Zmergesetmax,
|
||||
Zmergesettot2,
|
||||
Zmergesimplex,
|
||||
Zmergevertex,
|
||||
Wmindenom,
|
||||
Wminvertex,
|
||||
Zminnorm,
|
||||
Zmultiridge,
|
||||
Znearlysingular,
|
||||
Zredundant,
|
||||
Wnewbalance,
|
||||
Wnewbalance2,
|
||||
Znewbesthorizon,
|
||||
Znewfacettot,
|
||||
Znewfacetmax,
|
||||
Znewvertex,
|
||||
Wnewvertex,
|
||||
Wnewvertexmax,
|
||||
Znewvertexridge,
|
||||
Znoarea,
|
||||
Znonsimplicial,
|
||||
Znowsimplicial,
|
||||
Znotgood,
|
||||
Znotgoodnew,
|
||||
Znotmax,
|
||||
Znumfacets,
|
||||
Znummergemax,
|
||||
Znummergetot,
|
||||
Znumneighbors,
|
||||
Znumridges,
|
||||
Znumvertices,
|
||||
Znumvisibility,
|
||||
Znumvneighbors,
|
||||
Zonehorizon,
|
||||
Zpartangle,
|
||||
Zpartcoplanar,
|
||||
Zpartcorner,
|
||||
Zparthidden,
|
||||
Zpartinside,
|
||||
Zpartition,
|
||||
Zpartitionall,
|
||||
Zpartnear,
|
||||
Zparttwisted,
|
||||
Zpbalance,
|
||||
Wpbalance,
|
||||
Wpbalance2,
|
||||
Zpinchduplicate,
|
||||
Zpinchedapex,
|
||||
Zpinchedvertex,
|
||||
Zpostfacets,
|
||||
Zpremergetot,
|
||||
Zprocessed,
|
||||
Zremvertex,
|
||||
Zremvertexdel,
|
||||
Zredundantmerge,
|
||||
Zrenameall,
|
||||
Zrenamepinch,
|
||||
Zrenameshare,
|
||||
Zretry,
|
||||
Wretrymax,
|
||||
Zretryadd,
|
||||
Zretryaddmax,
|
||||
Zretryaddtot,
|
||||
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,
|
||||
Ztwisted,
|
||||
Wtwistedtot,
|
||||
Wtwistedmax,
|
||||
Ztwistedridge,
|
||||
Zvertextests,
|
||||
Wvertexmax,
|
||||
Wvertexmin,
|
||||
Zvertexridge,
|
||||
Zvertexridgetot,
|
||||
Zvertexridgemax,
|
||||
Zvertices,
|
||||
Zvisfacettot,
|
||||
Zvisfacetmax,
|
||||
Zvisit,
|
||||
Zvisit2max,
|
||||
Zvisvertextot,
|
||||
Zvisvertexmax,
|
||||
Zvvisit,
|
||||
Zvvisit2max,
|
||||
Zwidefacet,
|
||||
Zwidevertices,
|
||||
ZEND};
|
||||
|
||||
/*-<a href="qh-stat_r.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 qh_statistics { /* for zzdef etc. macros */
|
||||
Zback0,
|
||||
Zbestdist,
|
||||
Zcentrumtests,
|
||||
Zcheckpart,
|
||||
Zconcaveridges,
|
||||
Zcoplanarhorizon,
|
||||
Zcoplanarpart,
|
||||
Zcoplanarridges,
|
||||
Zcyclefacettot,
|
||||
Zcyclehorizon,
|
||||
Zdelvertextot,
|
||||
Zdistcheck,
|
||||
Zdistconvex,
|
||||
Zdistplane,
|
||||
Zdistzero,
|
||||
Zdoc1,
|
||||
Zdoc2,
|
||||
Zdoc3,
|
||||
Zdoc11,
|
||||
Zflippedfacets,
|
||||
Zflipridge,
|
||||
Zflipridge2,
|
||||
Zgauss0,
|
||||
Zminnorm,
|
||||
Zmultiridge,
|
||||
Znearlysingular,
|
||||
Wnewvertexmax,
|
||||
Znumvisibility,
|
||||
Zpartcoplanar,
|
||||
Zpartition,
|
||||
Zpartitionall,
|
||||
Zpinchduplicate,
|
||||
Zpinchedvertex,
|
||||
Zprocessed,
|
||||
Zretry,
|
||||
Zridge,
|
||||
Wridge,
|
||||
Wridgemax,
|
||||
Zridge0,
|
||||
Wridge0,
|
||||
Wridge0max,
|
||||
Zridgemid,
|
||||
Wridgemid,
|
||||
Wridgemidmax,
|
||||
Zridgeok,
|
||||
Wridgeok,
|
||||
Wridgeokmax,
|
||||
Zsetplane,
|
||||
Ztotcheck,
|
||||
Ztotmerge,
|
||||
Zvertextests,
|
||||
ZEND};
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-stat_r.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_r.htm#TOC"
|
||||
>--------------------------------</a><a name="MAYdebugx">-</a>
|
||||
|
||||
MAYdebugx
|
||||
define as maydebug() to be called frequently for error trapping
|
||||
*/
|
||||
#define MAYdebugx
|
||||
|
||||
/*-<a href="qh-stat_r.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) qh->qhstat.id[qh->qhstat.next++]=name; \
|
||||
qh->qhstat.doc[name]= string; qh->qhstat.count[name]= cnt; qh->qhstat.type[name]= stype
|
||||
#if qh_KEEPstatistics
|
||||
#define zdef_(stype,name,string,cnt) qh->qhstat.id[qh->qhstat.next++]=name; \
|
||||
qh->qhstat.doc[name]= string; qh->qhstat.count[name]= cnt; qh->qhstat.type[name]= stype
|
||||
#else
|
||||
#define zdef_(type,name,doc,count)
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>--------------------------------</a><a name="zinc_">-</a>
|
||||
|
||||
zzinc_( name ), zinc_( name)
|
||||
increment an integer statistic
|
||||
*/
|
||||
#define zzinc_(id) {MAYdebugx; qh->qhstat.stats[id].i++;}
|
||||
#if qh_KEEPstatistics
|
||||
#define zinc_(id) {MAYdebugx; qh->qhstat.stats[id].i++;}
|
||||
#else
|
||||
#define zinc_(id) {}
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-stat_r.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; qh->qhstat.stats[id].i += (val);}
|
||||
#define wwadd_(id, val) {MAYdebugx; qh->qhstat.stats[id].r += (val);}
|
||||
#if qh_KEEPstatistics
|
||||
#define zadd_(id, val) {MAYdebugx; qh->qhstat.stats[id].i += (val);}
|
||||
#define wadd_(id, val) {MAYdebugx; qh->qhstat.stats[id].r += (val);}
|
||||
#else
|
||||
#define zadd_(id, val) {}
|
||||
#define wadd_(id, val) {}
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>--------------------------------</a><a name="zval_">-</a>
|
||||
|
||||
zzval_( name ), zval_( name ), wwval_( name )
|
||||
set or return value of a statistic
|
||||
*/
|
||||
#define zzval_(id) ((qh->qhstat.stats[id]).i)
|
||||
#define wwval_(id) ((qh->qhstat.stats[id]).r)
|
||||
#if qh_KEEPstatistics
|
||||
#define zval_(id) ((qh->qhstat.stats[id]).i)
|
||||
#define wval_(id) ((qh->qhstat.stats[id]).r)
|
||||
#else
|
||||
#define zval_(id) qh->qhstat.tempi
|
||||
#define wval_(id) qh->qhstat.tempr
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-stat_r.htm#TOC"
|
||||
>--------------------------------</a><a name="zmax_">-</a>
|
||||
|
||||
zmax_( id, val ), wmax_( id, value )
|
||||
maximize id with val
|
||||
*/
|
||||
#define wwmax_(id, val) {MAYdebugx; maximize_(qh->qhstat.stats[id].r,(val));}
|
||||
#if qh_KEEPstatistics
|
||||
#define zmax_(id, val) {MAYdebugx; maximize_(qh->qhstat.stats[id].i,(val));}
|
||||
#define wmax_(id, val) {MAYdebugx; maximize_(qh->qhstat.stats[id].r,(val));}
|
||||
#else
|
||||
#define zmax_(id, val) {}
|
||||
#define wmax_(id, val) {}
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-stat_r.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_(qh->qhstat.stats[id].i,(val));}
|
||||
#define wmin_(id, val) {MAYdebugx; minimize_(qh->qhstat.stats[id].r,(val));}
|
||||
#else
|
||||
#define zmin_(id, val) {}
|
||||
#define wmin_(id, val) {}
|
||||
#endif
|
||||
|
||||
/*================== stat_r.h types ==============*/
|
||||
|
||||
|
||||
/*-<a href="qh-stat_r.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_r.htm#TOC"
|
||||
>--------------------------------</a><a name="qhstat">-</a>
|
||||
|
||||
qhstat
|
||||
Data structure for statistics, similar to qh and qhrbox
|
||||
|
||||
Allocated as part of qhT (libqhull_r.h)
|
||||
*/
|
||||
|
||||
struct qhstatT {
|
||||
intrealT stats[ZEND]; /* integer and real statistics */
|
||||
unsigned char id[ZEND+10]; /* id's in print order */
|
||||
const 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, printed on qh_errexit and qh_produce_output2/Q0/QJn */
|
||||
int vridges; /* index for Voronoi ridges, printed on qh_produce_output2 */
|
||||
int tempi;
|
||||
realT tempr;
|
||||
};
|
||||
|
||||
/*========== function prototypes ===========*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void qh_allstatA(qhT *qh);
|
||||
void qh_allstatB(qhT *qh);
|
||||
void qh_allstatC(qhT *qh);
|
||||
void qh_allstatD(qhT *qh);
|
||||
void qh_allstatE(qhT *qh);
|
||||
void qh_allstatE2(qhT *qh);
|
||||
void qh_allstatF(qhT *qh);
|
||||
void qh_allstatG(qhT *qh);
|
||||
void qh_allstatH(qhT *qh);
|
||||
void qh_allstatI(qhT *qh);
|
||||
void qh_allstatistics(qhT *qh);
|
||||
void qh_collectstatistics(qhT *qh);
|
||||
void qh_initstatistics(qhT *qh);
|
||||
boolT qh_newstats(qhT *qh, int idx, int *nextindex);
|
||||
boolT qh_nostatistic(qhT *qh, int i);
|
||||
void qh_printallstatistics(qhT *qh, FILE *fp, const char *string);
|
||||
void qh_printstatistics(qhT *qh, FILE *fp, const char *string);
|
||||
void qh_printstatlevel(qhT *qh, FILE *fp, int id);
|
||||
void qh_printstats(qhT *qh, FILE *fp, int idx, int *nextindex);
|
||||
realT qh_stddev(qhT *qh, int num, realT tot, realT tot2, realT *ave);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* qhDEFstat */
|
||||
@@ -0,0 +1,617 @@
|
||||
/*<html><pre> -<a href="qh-user_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
user_r.c
|
||||
user redefinable functions
|
||||
|
||||
see user2_r.c for qh_fprintf, qh_malloc, qh_free
|
||||
|
||||
see README.txt see COPYING.txt for copyright information.
|
||||
|
||||
see libqhull_r.h for data structures, macros, and user-callable functions.
|
||||
|
||||
see user_eg_r.c, user_eg2_r.c, and unix_r.c for examples.
|
||||
|
||||
see user_r.h for user-definable constants
|
||||
|
||||
use qh_NOmem in mem_r.h to turn off memory management
|
||||
use qh_NOmerge in user_r.h to turn off facet merging
|
||||
set qh_KEEPstatistics in user_r.h to 0 to turn off statistics
|
||||
|
||||
This is unsupported software. You're welcome to make changes,
|
||||
but you're on your own if something goes wrong. Use 'Tc' to
|
||||
check frequently. Usually qhull will report an error if
|
||||
a data structure becomes inconsistent. If so, it also reports
|
||||
the last point added to the hull, e.g., 102. You can then trace
|
||||
the execution of qhull with "T4P102".
|
||||
|
||||
Please report any errors that you fix to qhull@qhull.org
|
||||
|
||||
Qhull-template is a template for calling qhull from within your application
|
||||
|
||||
if you recompile and load this module, then user.o will not be loaded
|
||||
from qhull.a
|
||||
|
||||
you can add additional quick allocation sizes in qh_user_memsizes
|
||||
|
||||
if the other functions here are redefined to not use qh_print...,
|
||||
then io.o will not be loaded from qhull.a. See user_eg_r.c for an
|
||||
example. We recommend keeping io.o for the extra debugging
|
||||
information it supplies.
|
||||
*/
|
||||
|
||||
#include "qhull_ra.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="qhull_template">-</a>
|
||||
|
||||
Qhull-template
|
||||
Template for calling qhull from inside your program
|
||||
|
||||
returns:
|
||||
exit code(see qh_ERR... in libqhull_r.h)
|
||||
all memory freed
|
||||
|
||||
notes:
|
||||
This can be called any number of times.
|
||||
*/
|
||||
#if 0
|
||||
{
|
||||
int dim; /* dimension of points */
|
||||
int numpoints; /* number of points */
|
||||
coordT *points; /* array of coordinates for each point */
|
||||
boolT ismalloc; /* True if qhull should free points in qh_freeqhull() or reallocation */
|
||||
char flags[]= "qhull Tv"; /* option flags for qhull, see html/qh-quick.htm */
|
||||
FILE *outfile= stdout; /* output from qh_produce_output
|
||||
use NULL to skip qh_produce_output */
|
||||
FILE *errfile= stderr; /* error messages from qhull code */
|
||||
int exitcode; /* 0 if no error from qhull */
|
||||
facetT *facet; /* set by FORALLfacets */
|
||||
int curlong, totlong; /* memory remaining after qh_memfreeshort */
|
||||
|
||||
qhT qh_qh; /* Qhull's data structure. First argument of most calls */
|
||||
qhT *qh= &qh_qh; /* Alternatively -- qhT *qh= (qhT *)malloc(sizeof(qhT)) */
|
||||
|
||||
QHULL_LIB_CHECK /* Check for compatible library */
|
||||
|
||||
qh_zero(qh, errfile);
|
||||
|
||||
/* initialize dim, numpoints, points[], ismalloc here */
|
||||
exitcode= qh_new_qhull(qh, dim, numpoints, points, ismalloc,
|
||||
flags, outfile, errfile);
|
||||
if (!exitcode) { /* if no error */
|
||||
/* 'qh->facet_list' contains the convex hull */
|
||||
FORALLfacets {
|
||||
/* ... your code ... */
|
||||
}
|
||||
}
|
||||
qh_freeqhull(qh, !qh_ALL);
|
||||
qh_memfreeshort(qh, &curlong, &totlong);
|
||||
if (curlong || totlong)
|
||||
qh_fprintf(qh, errfile, 7079, "qhull internal warning (main): did not free %d bytes of long memory(%d pieces)\n", totlong, curlong);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="new_qhull">-</a>
|
||||
|
||||
qh_new_qhull(qh, dim, numpoints, points, ismalloc, qhull_cmd, outfile, errfile )
|
||||
Run qhull
|
||||
Before first call, either call qh_zero(qh, errfile), or set qh to all zero.
|
||||
|
||||
returns:
|
||||
results in qh
|
||||
exitcode (0 if no errors).
|
||||
|
||||
notes:
|
||||
do not modify points until finished with results.
|
||||
The qhull data structure contains pointers into the points array.
|
||||
do not call qhull functions before qh_new_qhull().
|
||||
The qhull data structure is not initialized until qh_new_qhull().
|
||||
do not call qh_init_A (global_r.c)
|
||||
|
||||
Default errfile is stderr, outfile may be null
|
||||
qhull_cmd must start with "qhull "
|
||||
projects points to a new point array for Delaunay triangulations ('d' and 'v')
|
||||
transforms points into a new point array for halfspace intersection ('H')
|
||||
|
||||
see:
|
||||
Qhull-template at the beginning of this file.
|
||||
An example of using qh_new_qhull is user_eg_r.c
|
||||
*/
|
||||
int qh_new_qhull(qhT *qh, int dim, int numpoints, coordT *points, boolT ismalloc,
|
||||
char *qhull_cmd, FILE *outfile, FILE *errfile) {
|
||||
/* gcc may issue a "might be clobbered" warning for dim, points, and ismalloc [-Wclobbered].
|
||||
These parameters are not referenced after a longjmp() and hence not clobbered.
|
||||
See http://stackoverflow.com/questions/7721854/what-sense-do-these-clobbered-variable-warnings-make */
|
||||
int exitcode, hulldim;
|
||||
boolT new_ismalloc;
|
||||
coordT *new_points;
|
||||
|
||||
if(!errfile){
|
||||
errfile= stderr;
|
||||
}
|
||||
if (!qh->qhmem.ferr) {
|
||||
qh_meminit(qh, errfile);
|
||||
} else {
|
||||
qh_memcheck(qh);
|
||||
}
|
||||
if (strncmp(qhull_cmd, "qhull ", (size_t)6) && strcmp(qhull_cmd, "qhull") != 0) {
|
||||
qh_fprintf(qh, errfile, 6186, "qhull error (qh_new_qhull): start qhull_cmd argument with \"qhull \" or set to \"qhull\"\n");
|
||||
return qh_ERRinput;
|
||||
}
|
||||
qh_initqhull_start(qh, NULL, outfile, errfile);
|
||||
if(numpoints==0 && points==NULL){
|
||||
trace1((qh, qh->ferr, 1047, "qh_new_qhull: initialize Qhull\n"));
|
||||
return 0;
|
||||
}
|
||||
trace1((qh, qh->ferr, 1044, "qh_new_qhull: build new Qhull for %d %d-d points with %s\n", numpoints, dim, qhull_cmd));
|
||||
exitcode= setjmp(qh->errexit);
|
||||
if (!exitcode) {
|
||||
qh->NOerrexit= False;
|
||||
qh_initflags(qh, qhull_cmd);
|
||||
if (qh->DELAUNAY)
|
||||
qh->PROJECTdelaunay= True;
|
||||
if (qh->HALFspace) {
|
||||
/* points is an array of halfspaces,
|
||||
the last coordinate of each halfspace is its offset */
|
||||
hulldim= dim-1;
|
||||
qh_setfeasible(qh, hulldim);
|
||||
new_points= qh_sethalfspace_all(qh, dim, numpoints, points, qh->feasible_point);
|
||||
new_ismalloc= True;
|
||||
if (ismalloc)
|
||||
qh_free(points);
|
||||
}else {
|
||||
hulldim= dim;
|
||||
new_points= points;
|
||||
new_ismalloc= ismalloc;
|
||||
}
|
||||
qh_init_B(qh, new_points, numpoints, hulldim, new_ismalloc);
|
||||
qh_qhull(qh);
|
||||
qh_check_output(qh);
|
||||
if (outfile) {
|
||||
qh_produce_output(qh);
|
||||
}else {
|
||||
qh_prepare_output(qh);
|
||||
}
|
||||
if (qh->VERIFYoutput && !qh->FORCEoutput && !qh->STOPadd && !qh->STOPcone && !qh->STOPpoint)
|
||||
qh_check_points(qh);
|
||||
}
|
||||
qh->NOerrexit= True;
|
||||
return exitcode;
|
||||
} /* new_qhull */
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="errexit">-</a>
|
||||
|
||||
qh_errexit(qh, exitcode, facet, ridge )
|
||||
report and exit from an error
|
||||
report facet and ridge if non-NULL
|
||||
reports useful information such as last point processed
|
||||
set qh.FORCEoutput to print neighborhood of facet
|
||||
|
||||
see:
|
||||
qh_errexit2() in libqhull_r.c for printing 2 facets
|
||||
|
||||
design:
|
||||
check for error within error processing
|
||||
compute qh.hulltime
|
||||
print facet and ridge (if any)
|
||||
report commandString, options, qh.furthest_id
|
||||
print summary and statistics (including precision statistics)
|
||||
if qh_ERRsingular
|
||||
print help text for singular data set
|
||||
exit program via long jump (if defined) or exit()
|
||||
*/
|
||||
void qh_errexit(qhT *qh, int exitcode, facetT *facet, ridgeT *ridge) {
|
||||
|
||||
qh->tracefacet= NULL; /* avoid infinite recursion through qh_fprintf */
|
||||
qh->traceridge= NULL;
|
||||
qh->tracevertex= NULL;
|
||||
if (qh->ERREXITcalled) {
|
||||
qh_fprintf(qh, qh->ferr, 8126, "\nqhull error while handling previous error in qh_errexit. Exit program\n");
|
||||
qh_exit(qh_ERRother);
|
||||
}
|
||||
qh->ERREXITcalled= True;
|
||||
if (!qh->QHULLfinished)
|
||||
qh->hulltime= qh_CPUclock - qh->hulltime;
|
||||
qh_errprint(qh, "ERRONEOUS", facet, NULL, ridge, NULL);
|
||||
qh_option(qh, "_maxoutside", NULL, &qh->MAXoutside);
|
||||
qh_fprintf(qh, qh->ferr, 8127, "\nWhile executing: %s | %s\n", qh->rbox_command, qh->qhull_command);
|
||||
qh_fprintf(qh, qh->ferr, 8128, "Options selected for Qhull %s:\n%s\n", qh_version, qh->qhull_options);
|
||||
if (qh->furthest_id >= 0) {
|
||||
qh_fprintf(qh, qh->ferr, 8129, "Last point added to hull was p%d.", qh->furthest_id);
|
||||
if (zzval_(Ztotmerge))
|
||||
qh_fprintf(qh, qh->ferr, 8130, " Last merge was #%d.", zzval_(Ztotmerge));
|
||||
if (qh->QHULLfinished)
|
||||
qh_fprintf(qh, qh->ferr, 8131, "\nQhull has finished constructing the hull.");
|
||||
else if (qh->POSTmerging)
|
||||
qh_fprintf(qh, qh->ferr, 8132, "\nQhull has started post-merging.");
|
||||
qh_fprintf(qh, qh->ferr, 8133, "\n");
|
||||
}
|
||||
if (qh->FORCEoutput && (qh->QHULLfinished || (!facet && !ridge)))
|
||||
qh_produce_output(qh);
|
||||
else if (exitcode != qh_ERRinput) {
|
||||
if (exitcode != qh_ERRsingular && zzval_(Zsetplane) > qh->hull_dim+1) {
|
||||
qh_fprintf(qh, qh->ferr, 8134, "\nAt error exit:\n");
|
||||
qh_printsummary(qh, qh->ferr);
|
||||
if (qh->PRINTstatistics) {
|
||||
qh_collectstatistics(qh);
|
||||
qh_allstatistics(qh);
|
||||
qh_printstatistics(qh, qh->ferr, "at error exit");
|
||||
qh_memstatistics(qh, qh->ferr);
|
||||
}
|
||||
}
|
||||
if (qh->PRINTprecision)
|
||||
qh_printstats(qh, qh->ferr, qh->qhstat.precision, NULL);
|
||||
}
|
||||
if (!exitcode)
|
||||
exitcode= qh_ERRother;
|
||||
else if (exitcode == qh_ERRprec && !qh->PREmerge)
|
||||
qh_printhelp_degenerate(qh, qh->ferr);
|
||||
else if (exitcode == qh_ERRqhull)
|
||||
qh_printhelp_internal(qh, qh->ferr);
|
||||
else if (exitcode == qh_ERRsingular)
|
||||
qh_printhelp_singular(qh, qh->ferr);
|
||||
else if (exitcode == qh_ERRdebug)
|
||||
qh_fprintf(qh, qh->ferr, 8016, "qhull exit due to qh_ERRdebug\n");
|
||||
else if (exitcode == qh_ERRtopology || exitcode == qh_ERRwide || exitcode == qh_ERRprec) {
|
||||
if (qh->NOpremerge && !qh->MERGING)
|
||||
qh_printhelp_degenerate(qh, qh->ferr);
|
||||
else if (exitcode == qh_ERRtopology)
|
||||
qh_printhelp_topology(qh, qh->ferr);
|
||||
else if (exitcode == qh_ERRwide)
|
||||
qh_printhelp_wide(qh, qh->ferr);
|
||||
}else if (exitcode > 255) {
|
||||
qh_fprintf(qh, qh->ferr, 6426, "qhull internal error (qh_errexit): exit code %d is greater than 255. Invalid argument for exit(). Replaced with 255\n", exitcode);
|
||||
exitcode= 255;
|
||||
}
|
||||
if (qh->NOerrexit) {
|
||||
qh_fprintf(qh, qh->ferr, 6187, "qhull internal error (qh_errexit): either error while reporting error QH%d, or qh.NOerrexit not cleared after setjmp(). Exit program with error status %d\n",
|
||||
qh->last_errcode, exitcode);
|
||||
qh_exit(exitcode);
|
||||
}
|
||||
qh->ERREXITcalled= False;
|
||||
qh->NOerrexit= True;
|
||||
qh->ALLOWrestart= False; /* longjmp will undo qh_build_withrestart */
|
||||
longjmp(qh->errexit, exitcode);
|
||||
} /* errexit */
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="errprint">-</a>
|
||||
|
||||
qh_errprint(qh, fp, string, atfacet, otherfacet, atridge, atvertex )
|
||||
prints out the information of facets and ridges to fp
|
||||
also prints neighbors and geomview output
|
||||
|
||||
notes:
|
||||
except for string, any parameter may be NULL
|
||||
*/
|
||||
void qh_errprint(qhT *qh, const char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
|
||||
int i;
|
||||
|
||||
if (atvertex) {
|
||||
qh_fprintf(qh, qh->ferr, 8138, "%s VERTEX:\n", string);
|
||||
qh_printvertex(qh, qh->ferr, atvertex);
|
||||
}
|
||||
if (atridge) {
|
||||
qh_fprintf(qh, qh->ferr, 8137, "%s RIDGE:\n", string);
|
||||
qh_printridge(qh, qh->ferr, atridge);
|
||||
if (!atfacet)
|
||||
atfacet= atridge->top;
|
||||
if (!otherfacet)
|
||||
otherfacet= otherfacet_(atridge, atfacet);
|
||||
if (atridge->top && atridge->top != atfacet && atridge->top != otherfacet)
|
||||
qh_printfacet(qh, qh->ferr, atridge->top);
|
||||
if (atridge->bottom && atridge->bottom != atfacet && atridge->bottom != otherfacet)
|
||||
qh_printfacet(qh, qh->ferr, atridge->bottom);
|
||||
}
|
||||
if (atfacet) {
|
||||
qh_fprintf(qh, qh->ferr, 8135, "%s FACET:\n", string);
|
||||
qh_printfacet(qh, qh->ferr, atfacet);
|
||||
}
|
||||
if (otherfacet) {
|
||||
qh_fprintf(qh, qh->ferr, 8136, "%s OTHER FACET:\n", string);
|
||||
qh_printfacet(qh, qh->ferr, otherfacet);
|
||||
}
|
||||
if (qh->fout && qh->FORCEoutput && atfacet && !qh->QHULLfinished && !qh->IStracing) {
|
||||
qh_fprintf(qh, qh->ferr, 8139, "ERRONEOUS and NEIGHBORING FACETS to output\n");
|
||||
for (i=0; i < qh_PRINTEND; i++) /* use fout for geomview output */
|
||||
qh_printneighborhood(qh, qh->fout, qh->PRINTout[i], atfacet, otherfacet,
|
||||
!qh_ALL);
|
||||
}
|
||||
} /* errprint */
|
||||
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="printfacetlist">-</a>
|
||||
|
||||
qh_printfacetlist(qh, fp, facetlist, facets, printall )
|
||||
print all fields for a facet list and/or set of facets to fp
|
||||
if !printall,
|
||||
only prints good facets
|
||||
|
||||
notes:
|
||||
also prints all vertices
|
||||
*/
|
||||
void qh_printfacetlist(qhT *qh, facetT *facetlist, setT *facets, boolT printall) {
|
||||
facetT *facet, **facetp;
|
||||
|
||||
if (facetlist)
|
||||
qh_checklists(qh, facetlist);
|
||||
qh_fprintf(qh, qh->ferr, 9424, "printfacetlist: vertices\n");
|
||||
qh_printbegin(qh, qh->ferr, qh_PRINTfacets, facetlist, facets, printall);
|
||||
if (facetlist) {
|
||||
qh_fprintf(qh, qh->ferr, 9413, "printfacetlist: facetlist\n");
|
||||
FORALLfacet_(facetlist)
|
||||
qh_printafacet(qh, qh->ferr, qh_PRINTfacets, facet, printall);
|
||||
}
|
||||
if (facets) {
|
||||
qh_fprintf(qh, qh->ferr, 9414, "printfacetlist: %d facets\n", qh_setsize(qh, facets));
|
||||
FOREACHfacet_(facets)
|
||||
qh_printafacet(qh, qh->ferr, qh_PRINTfacets, facet, printall);
|
||||
}
|
||||
qh_fprintf(qh, qh->ferr, 9412, "printfacetlist: end\n");
|
||||
qh_printend(qh, qh->ferr, qh_PRINTfacets, facetlist, facets, printall);
|
||||
} /* printfacetlist */
|
||||
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="printhelp_degenerate">-</a>
|
||||
|
||||
qh_printhelp_degenerate(qh, fp )
|
||||
prints descriptive message for precision error with qh_ERRprec
|
||||
|
||||
notes:
|
||||
no message if qh_QUICKhelp
|
||||
*/
|
||||
void qh_printhelp_degenerate(qhT *qh, FILE *fp) {
|
||||
|
||||
if (qh->MERGEexact || qh->PREmerge || qh->JOGGLEmax < REALmax/2)
|
||||
qh_fprintf(qh, fp, 9368, "\n\
|
||||
A Qhull error has occurred. Qhull should have corrected the above\n\
|
||||
precision error. Please send the input and all of the output to\n\
|
||||
qhull_bug@qhull.org\n");
|
||||
else if (!qh_QUICKhelp) {
|
||||
qh_fprintf(qh, fp, 9369, "\n\
|
||||
Precision problems were detected during construction of the convex hull.\n\
|
||||
This occurs because convex hull algorithms assume that calculations are\n\
|
||||
exact, but floating-point arithmetic has roundoff errors.\n\
|
||||
\n\
|
||||
To correct for precision problems, do not use 'Q0'. By default, Qhull\n\
|
||||
selects 'C-0' or 'Qx' and merges non-convex facets. With option 'QJ',\n\
|
||||
Qhull joggles the input to prevent precision problems. See \"Imprecision\n\
|
||||
in Qhull\" (qh-impre.htm).\n\
|
||||
\n\
|
||||
If you use 'Q0', the output may include\n\
|
||||
coplanar ridges, concave ridges, and flipped facets. In 4-d and higher,\n\
|
||||
Qhull may produce a ridge with four neighbors or two facets with the same \n\
|
||||
vertices. Qhull reports these events when they occur. It stops when a\n\
|
||||
concave ridge, flipped facet, or duplicate facet occurs.\n");
|
||||
#if REALfloat
|
||||
qh_fprintf(qh, fp, 9370, "\
|
||||
\n\
|
||||
Qhull is currently using single precision arithmetic. The following\n\
|
||||
will probably remove the precision problems:\n\
|
||||
- recompile qhull for realT precision(#define REALfloat 0 in user_r.h).\n");
|
||||
#endif
|
||||
if (qh->DELAUNAY && !qh->SCALElast && qh->MAXabs_coord > 1e4)
|
||||
qh_fprintf(qh, fp, 9371, "\
|
||||
\n\
|
||||
When computing the Delaunay triangulation of coordinates > 1.0,\n\
|
||||
- use 'Qbb' to scale the last coordinate to [0,m] (max previous coordinate)\n");
|
||||
if (qh->DELAUNAY && !qh->ATinfinity)
|
||||
qh_fprintf(qh, fp, 9372, "\
|
||||
When computing the Delaunay triangulation:\n\
|
||||
- use 'Qz' to add a point at-infinity. This reduces precision problems.\n");
|
||||
|
||||
qh_fprintf(qh, fp, 9373, "\
|
||||
\n\
|
||||
If you need triangular output:\n\
|
||||
- use option 'Qt' to triangulate the output\n\
|
||||
- use option 'QJ' to joggle the input points and remove precision errors\n\
|
||||
- use option 'Ft'. It triangulates non-simplicial facets with added points.\n\
|
||||
\n\
|
||||
If you must use 'Q0',\n\
|
||||
try one or more of the following options. They can not guarantee an output.\n\
|
||||
- use 'QbB' to scale the input to a cube.\n\
|
||||
- use 'Po' to produce output and prevent partitioning for flipped facets\n\
|
||||
- use 'V0' to set min. distance to visible facet as 0 instead of roundoff\n\
|
||||
- use 'En' to specify a maximum roundoff error less than %2.2g.\n\
|
||||
- options 'Qf', 'Qbb', and 'QR0' may also help\n",
|
||||
qh->DISTround);
|
||||
qh_fprintf(qh, fp, 9374, "\
|
||||
\n\
|
||||
To guarantee simplicial output:\n\
|
||||
- use option 'Qt' to triangulate the output\n\
|
||||
- use option 'QJ' to joggle the input points and remove precision errors\n\
|
||||
- use option 'Ft' to triangulate the output by adding points\n\
|
||||
- use exact arithmetic (see \"Imprecision in Qhull\", qh-impre.htm)\n\
|
||||
");
|
||||
}
|
||||
} /* printhelp_degenerate */
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="printhelp_internal">-</a>
|
||||
|
||||
qh_printhelp_internal(qh, fp )
|
||||
prints descriptive message for qhull internal error with qh_ERRqhull
|
||||
|
||||
notes:
|
||||
no message if qh_QUICKhelp
|
||||
*/
|
||||
void qh_printhelp_internal(qhT *qh, FILE *fp) {
|
||||
|
||||
if (!qh_QUICKhelp) {
|
||||
qh_fprintf(qh, fp, 9426, "\n\
|
||||
A Qhull internal error has occurred. Please send the input and output to\n\
|
||||
qhull_bug@qhull.org. If you can duplicate the error with logging ('T4z'), please\n\
|
||||
include the log file.\n");
|
||||
}
|
||||
} /* printhelp_internal */
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="printhelp_narrowhull">-</a>
|
||||
|
||||
qh_printhelp_narrowhull(qh, minangle )
|
||||
Warn about a narrow hull
|
||||
|
||||
notes:
|
||||
Alternatively, reduce qh_WARNnarrow in user_r.h
|
||||
|
||||
*/
|
||||
void qh_printhelp_narrowhull(qhT *qh, FILE *fp, realT minangle) {
|
||||
|
||||
qh_fprintf(qh, fp, 7089, "qhull precision warning: The initial hull is narrow. Is the input lower\n\
|
||||
dimensional (e.g., a square in 3-d instead of a cube)? Cosine of the minimum\n\
|
||||
angle is %.16f. If so, Qhull may produce a wide facet.\n\
|
||||
Options 'Qs' (search all points), 'Qbb' (scale last coordinate), or\n\
|
||||
'QbB' (scale to unit box) may remove this warning.\n\
|
||||
See 'Limitations' in qh-impre.htm. Use 'Pp' to skip this warning.\n",
|
||||
-minangle); /* convert from angle between normals to angle between facets */
|
||||
} /* printhelp_narrowhull */
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="printhelp_singular">-</a>
|
||||
|
||||
qh_printhelp_singular(qh, fp )
|
||||
prints descriptive message for singular input
|
||||
*/
|
||||
void qh_printhelp_singular(qhT *qh, FILE *fp) {
|
||||
facetT *facet;
|
||||
vertexT *vertex, **vertexp;
|
||||
realT min, max, *coord, dist;
|
||||
int i,k;
|
||||
|
||||
qh_fprintf(qh, fp, 9376, "\n\
|
||||
The input to qhull appears to be less than %d dimensional, or a\n\
|
||||
computation has overflowed.\n\n\
|
||||
Qhull could not construct a clearly convex simplex from points:\n",
|
||||
qh->hull_dim);
|
||||
qh_printvertexlist(qh, fp, "", qh->facet_list, NULL, qh_ALL);
|
||||
if (!qh_QUICKhelp)
|
||||
qh_fprintf(qh, fp, 9377, "\n\
|
||||
The center point is coplanar with a facet, or a vertex is coplanar\n\
|
||||
with a neighboring facet. The maximum round off error for\n\
|
||||
computing distances is %2.2g. The center point, facets and distances\n\
|
||||
to the center point are as follows:\n\n", qh->DISTround);
|
||||
qh_printpointid(qh, fp, "center point", qh->hull_dim, qh->interior_point, qh_IDunknown);
|
||||
qh_fprintf(qh, fp, 9378, "\n");
|
||||
FORALLfacets {
|
||||
qh_fprintf(qh, fp, 9379, "facet");
|
||||
FOREACHvertex_(facet->vertices)
|
||||
qh_fprintf(qh, fp, 9380, " p%d", qh_pointid(qh, vertex->point));
|
||||
zinc_(Zdistio);
|
||||
qh_distplane(qh, qh->interior_point, facet, &dist);
|
||||
qh_fprintf(qh, fp, 9381, " distance= %4.2g\n", dist);
|
||||
}
|
||||
if (!qh_QUICKhelp) {
|
||||
if (qh->HALFspace)
|
||||
qh_fprintf(qh, fp, 9382, "\n\
|
||||
These points are the dual of the given halfspaces. They indicate that\n\
|
||||
the intersection is degenerate.\n");
|
||||
qh_fprintf(qh, fp, 9383,"\n\
|
||||
These points either have a maximum or minimum x-coordinate, or\n\
|
||||
they maximize the determinant for k coordinates. Trial points\n\
|
||||
are first selected from points that maximize a coordinate.\n");
|
||||
if (qh->hull_dim >= qh_INITIALmax)
|
||||
qh_fprintf(qh, fp, 9384, "\n\
|
||||
Because of the high dimension, the min x-coordinate and max-coordinate\n\
|
||||
points are used if the determinant is non-zero. Option 'Qs' will\n\
|
||||
do a better, though much slower, job. Instead of 'Qs', you can change\n\
|
||||
the points by randomly rotating the input with 'QR0'.\n");
|
||||
}
|
||||
qh_fprintf(qh, fp, 9385, "\nThe min and max coordinates for each dimension are:\n");
|
||||
for (k=0; k < qh->hull_dim; k++) {
|
||||
min= REALmax;
|
||||
max= -REALmax;
|
||||
for (i=qh->num_points, coord= qh->first_point+k; i--; coord += qh->hull_dim) {
|
||||
maximize_(max, *coord);
|
||||
minimize_(min, *coord);
|
||||
}
|
||||
qh_fprintf(qh, fp, 9386, " %d: %8.4g %8.4g difference= %4.4g\n", k, min, max, max-min);
|
||||
}
|
||||
if (!qh_QUICKhelp) {
|
||||
qh_fprintf(qh, fp, 9387, "\n\
|
||||
If the input should be full dimensional, you have several options that\n\
|
||||
may determine an initial simplex:\n\
|
||||
- use 'QJ' to joggle the input and make it full dimensional\n\
|
||||
- use 'QbB' to scale the points to the unit cube\n\
|
||||
- use 'QR0' to randomly rotate the input for different maximum points\n\
|
||||
- use 'Qs' to search all points for the initial simplex\n\
|
||||
- use 'En' to specify a maximum roundoff error less than %2.2g.\n\
|
||||
- trace execution with 'T3' to see the determinant for each point.\n",
|
||||
qh->DISTround);
|
||||
#if REALfloat
|
||||
qh_fprintf(qh, fp, 9388, "\
|
||||
- recompile qhull for realT precision(#define REALfloat 0 in libqhull_r.h).\n");
|
||||
#endif
|
||||
qh_fprintf(qh, fp, 9389, "\n\
|
||||
If the input is lower dimensional:\n\
|
||||
- use 'QJ' to joggle the input and make it full dimensional\n\
|
||||
- use 'Qbk:0Bk:0' to delete coordinate k from the input. You should\n\
|
||||
pick the coordinate with the least range. The hull will have the\n\
|
||||
correct topology.\n\
|
||||
- determine the flat containing the points, rotate the points\n\
|
||||
into a coordinate plane, and delete the other coordinates.\n\
|
||||
- add one or more points to make the input full dimensional.\n\
|
||||
");
|
||||
}
|
||||
} /* printhelp_singular */
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="printhelp_topology">-</a>
|
||||
|
||||
qh_printhelp_topology(qh, fp )
|
||||
prints descriptive message for qhull topology error with qh_ERRtopology
|
||||
|
||||
notes:
|
||||
no message if qh_QUICKhelp
|
||||
*/
|
||||
void qh_printhelp_topology(qhT *qh, FILE *fp) {
|
||||
|
||||
if (!qh_QUICKhelp) {
|
||||
qh_fprintf(qh, fp, 9427, "\n\
|
||||
A Qhull topology error has occurred. Qhull did not recover from facet merges and vertex merges.\n\
|
||||
This usually occurs when the input is nearly degenerate and substantial merging has occurred.\n\
|
||||
See http://www.qhull.org/html/qh-impre.htm#limit\n");
|
||||
}
|
||||
} /* printhelp_topology */
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="printhelp_wide">-</a>
|
||||
|
||||
qh_printhelp_wide(qh, fp )
|
||||
prints descriptive message for qhull wide facet with qh_ERRwide
|
||||
|
||||
notes:
|
||||
no message if qh_QUICKhelp
|
||||
*/
|
||||
void qh_printhelp_wide(qhT *qh, FILE *fp) {
|
||||
|
||||
if (!qh_QUICKhelp) {
|
||||
qh_fprintf(qh, fp, 9428, "\n\
|
||||
A wide merge error has occurred. Qhull has produced a wide facet due to facet merges and vertex merges.\n\
|
||||
This usually occurs when the input is nearly degenerate and substantial merging has occurred.\n\
|
||||
See http://www.qhull.org/html/qh-impre.htm#limit\n");
|
||||
}
|
||||
} /* printhelp_wide */
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="user_memsizes">-</a>
|
||||
|
||||
qh_user_memsizes(qh)
|
||||
allocate up to 10 additional, quick allocation sizes
|
||||
|
||||
notes:
|
||||
increase maximum number of allocations in qh_initqhull_mem()
|
||||
*/
|
||||
void qh_user_memsizes(qhT *qh) {
|
||||
|
||||
QHULL_UNUSED(qh)
|
||||
/* qh_memsize(qh, size); */
|
||||
} /* user_memsizes */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,102 @@
|
||||
/*<html><pre> -<a href="qh-user_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
usermem_r.c
|
||||
user redefinable functions -- qh_exit, qh_free, and qh_malloc
|
||||
|
||||
See README.txt.
|
||||
|
||||
If you redefine one of these functions you must redefine all of them.
|
||||
If you recompile and load this file, then usermem.o will not be loaded
|
||||
from qhull.a or qhull.lib
|
||||
|
||||
See libqhull_r.h for data structures, macros, and user-callable functions.
|
||||
See user_r.c for qhull-related, redefinable functions
|
||||
see user_r.h for user-definable constants
|
||||
See userprintf_r.c for qh_fprintf and userprintf_rbox_r.c for qh_fprintf_rbox
|
||||
|
||||
Please report any errors that you fix to qhull@qhull.org
|
||||
*/
|
||||
|
||||
#include "libqhull_r.h"
|
||||
|
||||
#include "igraph_error.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="qh_exit">-</a>
|
||||
|
||||
qh_exit( exitcode )
|
||||
exit program
|
||||
the exitcode must be 255 or less. Zero indicates success.
|
||||
Note: Exit status ('$?') in bash reports 256 as 0
|
||||
|
||||
notes:
|
||||
qh_exit() is called when qh_errexit() and longjmp() are not available.
|
||||
|
||||
This is the only use of exit() in Qhull
|
||||
To replace qh_exit with 'throw', see libqhullcpp/usermem_r-cpp.cpp
|
||||
*/
|
||||
void qh_exit(int exitcode) {
|
||||
/* exit(exitcode); */
|
||||
/* This code is not reachable. We comment out exit() to ensure
|
||||
* that the igraph shared library does not reference it. */
|
||||
IGRAPH_FATALF("Qhull called exit() with exit code %d.", exitcode);
|
||||
} /* exit */
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="qh_fprintf_stderr">-</a>
|
||||
|
||||
qh_fprintf_stderr( msgcode, format, list of args )
|
||||
fprintf to stderr with msgcode (non-zero)
|
||||
|
||||
notes:
|
||||
qh_fprintf_stderr() is called when qh.ferr is not defined, usually due to an initialization error
|
||||
if msgcode is a MSG_ERROR (6000), caller should set qh.last_errcode (like qh_fprintf) or variable 'last_errcode'
|
||||
|
||||
It is typically followed by qh_errexit().
|
||||
|
||||
Redefine this function to avoid using stderr
|
||||
|
||||
Use qh_fprintf [userprintf_r.c] for normal printing
|
||||
*/
|
||||
void qh_fprintf_stderr(int msgcode, const char *fmt, ... ) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
if(msgcode)
|
||||
fprintf(stderr, "QH%.4d ", msgcode);
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
} /* fprintf_stderr */
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="qh_free">-</a>
|
||||
|
||||
qh_free(qh, mem )
|
||||
free memory
|
||||
|
||||
notes:
|
||||
same as free()
|
||||
No calls to qh_errexit()
|
||||
*/
|
||||
void qh_free(void *mem) {
|
||||
free(mem);
|
||||
} /* free */
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="qh_malloc">-</a>
|
||||
|
||||
qh_malloc( mem )
|
||||
allocate memory
|
||||
|
||||
notes:
|
||||
same as malloc()
|
||||
*/
|
||||
void *qh_malloc(size_t size) {
|
||||
return malloc(size);
|
||||
} /* malloc */
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*<html><pre> -<a href="qh-user_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
userprintf_r.c
|
||||
user redefinable function -- qh_fprintf
|
||||
|
||||
see README.txt see COPYING.txt for copyright information.
|
||||
|
||||
If you recompile and load this file, then userprintf_r.o will not be loaded
|
||||
from qhull_r.a or qhull_r.lib
|
||||
|
||||
See libqhull_r.h for data structures, macros, and user-callable functions.
|
||||
See user_r.c for qhull-related, redefinable functions
|
||||
see user_r.h for user-definable constants
|
||||
See usermem_r.c for qh_exit(), qh_free(), and qh_malloc()
|
||||
see Qhull.cpp and RboxPoints.cpp for examples.
|
||||
|
||||
qh_printf is a good location for debugging traps, checked on each log line
|
||||
|
||||
Please report any errors that you fix to qhull@qhull.org
|
||||
*/
|
||||
|
||||
#include "libqhull_r.h"
|
||||
#include "poly_r.h" /* for qh.tracefacet */
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="qh_fprintf">-</a>
|
||||
|
||||
qh_fprintf(qh, fp, msgcode, format, list of args )
|
||||
print arguments to *fp according to format
|
||||
Use qh_fprintf_rbox() for rboxlib_r.c
|
||||
|
||||
notes:
|
||||
sets qh.last_errcode if msgcode is error 6000..6999
|
||||
same as fprintf()
|
||||
fgets() is not trapped like fprintf()
|
||||
exit qh_fprintf via qh_errexit()
|
||||
may be called for errors in qh_initstatistics and qh_meminit
|
||||
*/
|
||||
|
||||
void qh_fprintf(qhT *qh, FILE *fp, int msgcode, const char *fmt, ... ) {
|
||||
va_list args;
|
||||
if (qh) {
|
||||
if (msgcode >= MSG_ERROR && msgcode < MSG_WARNING) {
|
||||
qh->last_errcode = msgcode;
|
||||
}
|
||||
if (qh->FLUSHprint) {
|
||||
fflush(fp);
|
||||
}
|
||||
}
|
||||
if (!fp) {
|
||||
return;
|
||||
}
|
||||
if ((qh && qh->ANNOTATEoutput) || msgcode < MSG_TRACE4) {
|
||||
fprintf(fp, "[QH%.4d]", msgcode);
|
||||
} else if (msgcode >= MSG_ERROR && msgcode < MSG_STDERR ) {
|
||||
fprintf(fp, "QH%.4d ", msgcode);
|
||||
}
|
||||
va_start(args, fmt);
|
||||
vfprintf(fp, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
} /* qh_fprintf */
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*<html><pre> -<a href="qh-user_r.htm"
|
||||
>-------------------------------</a><a name="TOP">-</a>
|
||||
|
||||
userprintf_rbox_r.c
|
||||
user redefinable function -- qh_fprintf_rbox
|
||||
|
||||
see README.txt see COPYING.txt for copyright information.
|
||||
|
||||
If you recompile and load this file, then userprintf_rbox_r.o will not be loaded
|
||||
from qhull.a or qhull.lib
|
||||
|
||||
See libqhull_r.h for data structures, macros, and user-callable functions.
|
||||
See user_r.c for qhull-related, redefinable functions
|
||||
see user_r.h for user-definable constants
|
||||
See usermem_r.c for qh_exit(), qh_free(), and qh_malloc()
|
||||
see Qhull.cpp and RboxPoints.cpp for examples.
|
||||
|
||||
Please report any errors that you fix to qhull@qhull.org
|
||||
*/
|
||||
|
||||
#include "libqhull_r.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*-<a href="qh-user_r.htm#TOC"
|
||||
>-------------------------------</a><a name="qh_fprintf_rbox">-</a>
|
||||
|
||||
qh_fprintf_rbox(qh, fp, msgcode, format, list of args )
|
||||
print arguments to *fp according to format
|
||||
Use qh_fprintf_rbox() for rboxlib_r.c
|
||||
|
||||
notes:
|
||||
same as fprintf()
|
||||
fgets() is not trapped like fprintf()
|
||||
exit qh_fprintf_rbox via qh_errexit_rbox()
|
||||
*/
|
||||
|
||||
void qh_fprintf_rbox(qhT *qh, FILE *fp, int msgcode, const char *fmt, ... ) {
|
||||
va_list args;
|
||||
|
||||
if (!fp) {
|
||||
qh_fprintf_stderr(6231, "qhull internal error (userprintf_rbox_r.c): fp is 0. Wrong qh_fprintf_rbox called.\n");
|
||||
qh_errexit_rbox(qh, qh_ERRqhull);
|
||||
}
|
||||
if (msgcode >= MSG_ERROR && msgcode < MSG_STDERR)
|
||||
fprintf(fp, "QH%.4d ", msgcode);
|
||||
va_start(args, fmt);
|
||||
vfprintf(fp, fmt, args);
|
||||
va_end(args);
|
||||
} /* qh_fprintf_rbox */
|
||||
|
||||
Reference in New Issue
Block a user