diff --git a/.gitignore b/.gitignore
index 5afc0b0..7d1a224 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,66 +1,77 @@
# git-ls-files --others --ignored
# Lines that start with '#' are comments.
+# Working files 2015
+# Need to clean up bin/ and build/ for git
+bin/
+build/
+build-mar14/
+build-new/
+buildqt/
+buildvc/
+src/qhulltest/qhulltest-mini.pro
+src/qhulltest/RoadTest.h.cpp
+
# Backup and data files
eg/eg.*
*~
*.bak
*.off
*.x
x.*
r
x
x?
r?
# patch results
*.rej
# Build products
tmp/*
build-cmake/*
build/Debug/*
build/moc/*
build/qhulltest/*
build/Release/*
build/cmake_install.cmake
build/CMakeCache.txt
build/CMakeFiles
build/install_manifest.txt
build/Makefile*
build/*/Makefile*
build/*/object_script*
build/*/Release/*
build/*/Debug/*
build/*/MinSizeRel/*
build/*/RelWithDebInfo/*
lib
*.a
*.dll
*.idb
*.lib
*.exe
*.o
*.md5sum
# Qt files
*.pro.user
# DevStudio files
*.bsc
*.ncb
*.pdb
*.suo
*.user
*.ilk
# CVS files
CVS/*
*/CVS/*
*/*/CVS/*
*/*/*/CVS/*
*.cvsignore
# Other files
working/
diff --git a/eg/make-vcproj.sh b/eg/make-vcproj.sh
index 90f3450..faee9eb 100644
--- a/eg/make-vcproj.sh
+++ b/eg/make-vcproj.sh
@@ -1,83 +1,84 @@
#!/bin/bash
#
# make-vcproj.sh -- Make sln and vcproj files from CMakeLists.txt and qhull-all.pro
#
# [jan'12] Additional changes made by hand for qhull 2012.1. This file updated but not tested.
#
# $Id: //main/2011/qhull/eg/make-vcproj.sh#5 $$Change: 1476 $
# $DateTime: 2012/01/28 09:37:56 $$Author: bbarber $
if [[ ! -f CMakeLists.txt || ! -f src/qhull-all.pro ]]; then
echo "Excute eg/make-vcproj.sh from qhull directory with CMakeLists.txt and src/qhull-all.pro"
exit
fi
echo "Set up build directories..."
if [[ ! -d build-prev ]]; then
echo "Backup previous build"
cp -r build build-prev && rm -r build
fi
rm -r buildvc buildqt
mkdir -p build
mkdir -p buildvc
mkdir -p buildqt
echo "Create vcproj files with cmake and qmake..."
cd buildvc && cmake -G "Visual Studio 8 2005" .. && cmake ..
cd ..
cd buildqt && qmake -tp vc -r ../src/qhull-all.pro
cd ..
if [[ ! -f CMakeLists.txt || ! -f buildvc/qhull.vcproj || ! -f buildqt/qhulltest/qhulltest.vcproj ]]; then
echo "qmake and cmake did not build vcproj files in buildvc/ and buildqt"
exit
fi
for f in buildvc/*.vcproj buildqt/qhulltest/*.vcproj; do
echo $f
if [[ ! ${f##*INSTALL*} || ! ${f##*ALL_BUILD*} || ! ${f##*ZERO_CHECK*} ]]; then
continue
fi
dest=build/${f##*\/}
sed -r -e 's|[cC]:\\bash\\local\\qhull|..|g' \
-e 's|[cC]:/bash/local/qhull|..|g' \
-e '\|CMake| d' \
-e 's/;CMAKE_INTDIR=..quot;[A-Za-z]*..quot;//' \
-e 's/LinkIncremental="2"/LinkIncremental="1"/' \
-e 's/RuntimeLibrary[=]/RuntimeTypeInfo="false" RuntimeLibrary=/' \
-e 's/.*RuntimeTypeInfo."TRUE".*//' \
-e 's/buildvc/build/g' \
-e 's/buildqt/build/g' \
-e 's/\.\.\\\.\./../g' \
-e 's|\.\./\.\.|..|g' \
-e 's/c:\\qt\\[0-9]\.[0-9]\.[0-9]/\$(QTDIR)/g' \
-e 's|..\\build\\[a-zA-Z]*[\\/]([_a-z0-9]*.pdb)|..\\bin\\\1|g' \
-e 's|..\\build\\[a-zA-Z]*[\\/]([_a-z0-9]*.exe)|..\\bin\\\1|g' \
-e 's|..\\build\\[a-zA-Z]*[\\/]([_a-z0-9]*.lib)|..\\lib\\\1|g' \
-e 's|..\\build\\[a-zA-Z]*[\\/]([_a-z0-9]*.dll)|..\\bin\\\1|g' \
-e 's| [a-zA-Z]*[\\/]([_a-z0-9]*.lib)| ..\\lib\\\1|g' \
-e 's/"([_a-z0-9]*.exe)/"..\\bin\\\1/g' \
$f > $dest
done
-echo -e '\nExcept for qhulltest.vcproj,\n*.vcproj: delete empty File in Files section near end of vcproj'
-echo -e '\nExcept for qhulltest.vcproj,\n*.vcproj: rename debug targets to qhull_d.dll, etc.'
+echo -e '\nExcept for qhulltest.vcproj,\n*.vcproj: [mar'14 none] delete empty File in Files section near end of vcproj'
+echo -e '\nExcept for qhulltest.vcproj,\n*.vcproj: [mar'14 where?] rename debug targets to qhull_d.dll, etc.'
# If need to rebuild sln
sed -e '\|Project.*ALL_BUILD|,\|EndProject$| d' \
-e '\|Project.*INSTALL|,\|EndProject$| d' \
-e '\|Project.*ZERO_CHECK|,\|EndProject$| d' \
buildvc/qhull.sln >build/qhull.sln
echo
-echo 'qhull.sln: Remove first line of each GUID list -- postProject\n.* > postProject'
-echo 'qhull.sln: Remove four empty project sections'
-echo 'qhull.sln: Remove first part of Global section.'
+echo 'qhull.sln: Identify the GUID on the first line of each list.'
+echo 'qhull.sln: Remove first part of Global section down to this GUID'
+echo 'qhull.sln: Remove this GUID from each GUID list -- postProject\n.* > postProject'
+echo 'qhull.sln: Remove five empty project sections'
echo 'qhull.sln: Save as PC'
-echo '*.vcproj: Remove libqhullcpp from AdditionalIncludeDirectories except for cpp'
+echo '\nExcept for libqhullcpp, libqhullpcpp, qhulltest, user_eg3\n*.vcproj: Remove "..\src\libqhullcpp;" from AdditionalIncludeDirectories'
echo
echo 'Open qhull.sln with DevStudio and add qhulltest.vcproj'
echo 'Add dependencies on libqhull libqhull6_p and qhullcpp'
echo 'Change Linker>OutputFile to qhulltest.exe'
echo 'Remove qhulltest via Configuration Manager from Release, Debug, etc.'
diff --git a/html/Changes.txt b/html/Changes.txt
deleted file mode 100644
index 724c6a1..0000000
--- a/html/Changes.txt
+++ /dev/null
@@ -1,890 +0,0 @@
-$Id: //main/2005/thid/src/Changes.txt#124 $$Change: 1496 $$Date: 2012/02/23 $
-
- ThError.THIDlastError 20107
- throw ThError(10527, "");
-
- install qInstallMsgHandler
-
- Store thid_sha1 along with data
- store thidid, sha1, blockid, date -- but already in thid-info. Allows re-creation.
- can't reallocate a blockid in the same second?
- sha1-out-of-date only needs to go up through in-date ones.
- Recursive algorithm -- depth first search -- writes new blockids as a blockid?
- blockids become invalid if any component changes
- thid sha1
- tuples of blockids => tuples of sha1
- tuples? of group thids -> tuples of sha1
- other tuples as is
- where are groups stored? as a block? grabbed from header? -- usually -- but its compressed
-
- Add an 'unknown' test, equivalent to NULL. But then need to make it a type
-Need
- Dump program -- serialized/wire format as sha1 blocks
- need blockid to sha1 and sha1 to blockid
- Minimal reuse of blockIds
- Review low-level syntax
- Is Print/Dump simply well known names?
- Auto propagate
- Editor
- Data representation as tuples
-
-
- why can I have two views open of the same DB?
- setThid should change focus to thid's window
-
- recursive calls require an explicit reference -- assumes a termination proof
- strict aliasing
- pointers are smart unless otherwise marked
-
- Editor
- No wrap
-
- Label ID.next needed for goto's
- Label ID.title needed for programs
- Label 0.title needed for unresolved programs
- addArgument makes 0.title an operand, but it is not used
- addOperand of 0.title gets the non-label version
- Undo the 0.title operand?
- Reset its name? OK if 0?
- Problem of literal vs. local literal
- Do I need a new arg type for label?
-
- A call in the same depot
-
- concept of local literals
- Add line numbers to ThCode parse errrors
- Add atomic primitive -- ==6->
- Need assigned-type for mispellings
- Need formated print instead of printSpace == ==
- Need ThCode::printProgram
- check for empty arguments in ThCode (addArgument, etc.) -- around split?
- Scan for valid primitive, maybe primitive
- ?.?= ? first equals after matching pattern
- ?==? -> ? first equals, last ->
- -> ? No -> in labels
- ? -> ? Try... then
-
- why is non-const operator[] selected for
- QStringList compare= RoadUtility::splitFirst(instruction, comparison);
- QStringList gotoLabel= RoadUtility::splitLast(compare[1], QString("->"));
-
- static QStringList splitFirst(const QString &s, const QString &sep, int from= 0, Qt::CaseSensitivity cs= Qt::CaseSensitive);
- Add VAX configuration (e.g., clips) into perforce
-
- want a list of thids. A ThidListSelector("xpath") e.g., qml or goes to a localId
-
- Goal of storing/editing notes/code and executing code
- Get language encodings
- On Thid::writeToDisk, also write its ThDepot
- static function QApplication::focusWidget()
- #ifndef Q_MOC_RUN
-
- Need ThDiskBlock for Thid
- get language. Then work on structured text.
- Reserve Depot: ... as name for depots.
- want to check in VAX configuration
- Not written to disk, no bootBlocks either
-
- execute a Thid
- UI
-
- Need to specify how a lower version handles a higher version. Note MIME is frozen at 1.0
-
-============================================
-== At home
-============================================
-
- Get copy of git
-
-unsigned access to byte array via uchar c= uchar(...)
-
-As a pointer or return a reference if modified?
-
-reassign F12 to a different key
-RegisterHotKey -- The F12 key is reserved for use by the debugger at all times, so it should not be registered as a hot key. Even when you are not debugging an application, F12 is reserved in case a kernel-mode debugger or a just-in-time debugger is resident.
-
-Need better solution than cout<<
-
-Need doc links between QApplication and QMainWindow
-
-Where to trap errors in UI -- throws caught by QMetaObject::activate when invoking a signal, e.g., gotoNewFile
-
-QApplication: contradicts constructor doc
- it is usually a good idea to create it before any interpretation or modification of argv is done in the application itself.
-
-How to hid item-ids in text -- should be a glyph How to work with QRegExp
-QTextFormat::UserObject
-
-int QTextCursor::blockNumber () const
-Returns the number of the block the cursor is in, or 0 if the cursor is invalid.
-Note that this function only makes sense in documents without complex objects such as tables or frames.
-
-Need context menu and Tools->Bookmarks menu for 'add bookmark'. QtCreator only has an add bookmark button
-Peter Abelard (1079-1142) diversity of authoratative opinion
-
-QTest -- ignore failures mode
-
-In debugger, shows as QObject instead of QTextDoument
- QTextDocument *text= main_ui.content_view_a->document();
-
- // QList displays as int in debugger
- // Problem of readLine() w/o line terminator -- runs forever
- // No equivalent to "has" for a QList (index within bounds
-
-Provide a template layout for .h with constructors, virtual methods, get/set, etc.
-
-Add SplitFirst and SplitLast to QString::SplitBehavior
-
----------------
-programs.txt
-
-Fix spacing in snippets
-
-Get MIME standard and yaml standard
-
-Guidelines
-----------
-fieldAt(const char *fieldStart, const char **fieldEnd/*= 0*/) const
-
-Support
--------
-
-QDir::remove() -- how to tell reason that a remove failed?
-
-Why is qrc code in QDir?
-void Q_CLEANUP_RESOURCE ( name )
-Unloads the resources specified by the .qrc file with th
-
-List of filename substrings to ignore. Auto switch between files on alt-o
-
-QString::chop not referenced from remove()
-
-Create from Usage gets $SymbolName$ and $SymbolType$ reversed in snippet
-
-'foreach keyword' doesn't say how to create foreach for yourself. Not in index.
-
-foreach requires T::const_iterator, begin(), and end()
-
-Create implementation not defined for multiple lines
-
-How to use QStringBuilder over multiple assignments
-
-Refactor Rename is a modal dialog box. Should allow navigation to investigate hits.
-
-How to open a QFile for exclusive access
-
-Change Signature does not preserve internal spacing
- bool tryCheckOwner(const ThDiskBlockId &b, const ThidHandle &owner, int howOwned);
-
-QByteArray documentation
-If data is 0, a null byte array is constructed.
-QByteArray::QByteArray(const char *data, int size)
-{
- if (!data) {
- d = &shared_null;
- } else if (size <= 0) {
- d = &shared_empty;
-
-
-Comments can do name expansion on initial or internal cap
-
-QTestLib manual
-Creating a Benchmark
-
-To create a benchmark, follow the instructions for crating a tes
-
-Need $SymbolClass$ (complements $SymbolName$ and $SymbolContext$
-
-$end$ did not work (all selected) -- $SymbolContext$$end$
-
-Refactor Selection, should run Create Implementation on each line in selection
-
-Snippets
----------
-
-@token@ @1@ @xmlns:thi@ @RS_FIRST@ @AT_START@ @{\rtf@ @^\{\\rtf\d+ ?@ @RA_ATTRIBUTE@ @@ @AT_NEXT_WHERE@ @@ @pv@
-@pv@ @freepool@ @1@ @129@ @234232@ @pv@
-
-@hd@ @thdisk@ @1@ @diskBlockId@ @hd@
-@pv@ @thdisk@ @1@ @0x32234221@ @pv@
-
-#if defined(Q_CC_MSVC) // Disable warning for 0x80 as type 'char'
-# pragma warning(disable: 4309) /* 'initializing' : truncation of constant value */
-#endif
-
-
-ToDo
-----
- need Statistics object using unique ids.
- change to const char *
- static const QString ThidHex128RE; //!< "-1234567890abcdef..." 32 hex digits, md5sum
-
- Change ThDiskBlock to QObject
- Rename ThItem to ThBlock
- use RoadError
- convert ItemFlags to QFlag
- Move flags to ThItem from ThAbstractItem
-
- ThSettings * ThSettings::s_thid_configuration= 0;
- remove handleForThid -- using field instead
- determineThidFromName -- convert string to char array
- Rethink ThidInfo format -- how to name things
- ThField.h is not standalone
- Fixed moc by linking with the the 2009.05 version
- qHash(Thesa::ThidIdentifier *t) { return qHash(static_cast(*t)) ^ qHash(t.second); };
- Bug in notes-dump.xml -- \n"par"
-
- need conventions for error reporting e.g. determineHandleForThid
-
- Rename determineHandle to assignHandle
-
-Test coverage
- Read all routines in _test and *.h and make sure that they match
- Check all error codes in _test and *.cpp
-
-============================================
-== History
-============================================
-
-.............This file lists all changes to thid.....................
-
-[Nov'11]
- Can create a persistent thid and execute 'Hello World'
-
-[feb'11]
- Can create thid/.. with boot blocks
-
-[jan'11]
- Can create and read bootBlock for a ThDiskBlockPool
-
-[nov'10]
- Can open an empty database and manipulate its configuration (first sector, etc)
- Can find and allocate a previously freed block id
-
- get number of sectors needed
- if fits, rewrite as free sector and remainders
- get enough sectors,
- if any not free, check if in freepool, add previous to freepool and repeat
- if last fits, add previous to freepool and break
- if out-of-sectors
- allocate more sectors (i.e., advance size of remainders)
- rewrite as free sector and remainders
- next_sector is after allocated sector
-
- Write a block id
-
-[oct'10]
- Can read and write ThDiskBlockHeader from ThDiskBlock
- Need blockIds on disk > Need BlockPool and free blocks > Need files
-
-[aug'10] Want data on disk.
- A pool file of everything
- A free list is a list of blockids. duplicated on the disk
-
-
-============================================
-== Notes on QAbstractModelIndex
-============================================
-
-Incomplete description "The underlying data model...". This is describing a tableView, not the item view.
-Make parent clear.
-
-The root is a table of rows and columns.
-Each cell of the table is a collection of role:value pairs, a set of flags, and an optional table (hasChildren)
-Roles are numbers, 0..31 are reserved by Qt. The values are QVariant
-The 'index' of a cell is its row, column, and parent in the model.
-'sibling' is the same as index(row,column, index.parent())
-Document meaning of QModelIndex::operator<
-
-Common models
- A list, column 0
- A table, no children
- A tree, column 0 has chidren (c.f., parent()). Other columns can provide associated information.
-
-Model Subclassing reference
- Read-only access
- Editable access
- No mention that QListView requires EditRole for data()
- No mention that QDataWidgetMapper::populate invokes QItemDelegate::setEditorData which requires EditRole
- void QDataWidgetMapperPrivate::populate(WidgetMapper &m)
-
----
-Why enabled if invalid
-addressbook example
-Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
-{
- if (!index.isValid())
- return Qt::ItemIsEnabled;
-
- return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
-}
-//! [7]
-
-----
-
-Methods alphabetical with [private]
-Editor.gotoNextLocation
-create... is same as new... but void return
-
-$(QTDIR)\include
-$(QTDIR)\include\Qt
-$(QTDIR)\include\QtCore
-$(QTDIR)\include\QtGui
-$(QTDIR)\include\QtHelp
-$(QTDIR)\include\QtNetwork
-$(QTDIR)\include\QtOpenGL
-$(QTDIR)\include\QtScript
-$(QTDIR)\include\QtSql
-$(QTDIR)\include\QtSvg
-$(QTDIR)\include\QtTest
-$(QTDIR)\include\QtUiTools
-$(QTDIR)\include\QtWebKit
-$(QTDIR)\include\QtXml
-$(QTDIR)\include\QtXmlPatterns
-$(QTDIR)\src
-
-Source maintenance (jul'11)
- Search for missing P4: \:[^a-zA-Z0-9]*\$
- Search for missing date: -2010
-
-============================================
-== Notes on ThDisk
-============================================
-
-Problem of ThidIdentifier::thidHash32 (for ThidDepot::computeThidIdentifer)
-and ThDiskThidPool::thidHash32 for hash bucket
-
- By default, hash of depot+label w/ depot is itemid
- getunique find an item id in the same bucket by common bits
- Sorted and Unsorted 4-byte hash + 8 byte block-id
- QMultiHash for staging -- store compress -- 55K
- Bits for Recent and New
- Need split and merge buckets
- write QMultiHash and buckets to two files
- rebuild by streaming into large QMultiHash, and flushing to bucket
- cally ygetidhash ;;get HashItemID, OtherHash for ItemID and BlockID, Different?
- cally yaddidhash ;;.add HashItemID, OtherHash, BlockID to ItemTable and ItemCache
- ynewitem creates ItemId for LabelFieldId, optional TitleId and precomputed size
- called by createitem ;;create ItemId, BlockId, and Title for Syntax .label, TitleID, and DepotItemId with SyntaxTable
- called by maybenew ;;maybe new ItemId and Title at TitleText and TitleID
-
- want ThItemId with a ThDiskBlockId containing title, owner itemid, depot itemid, and text
- want title lookup to itemId and diskBlockId
-
- Change to BlockType enum
-
- set next_empty+sector at boot
- next_empty_sector -- always valid
- reset after emptied
- search from end of file
- sector header is zero, sector tail is zero
- allow intermediate mode for sector rewrites
-
-A) Need a label hash -- same as Thesa for 24-bit IDs. Hash function by Depot's itemId size
- ygetidhash -- Hash a 24-bit itemid and its blockid (i.e., Label) for shared itemid-label buckets
- ylblhash -- 32-bit Hash of itemid label and DepotId (8-bit)
- remidhash -- removes hash-itemid and its blockid from curcache.
-
-B) Need a multi-level hash for
- LabelHash -> BlockId of corresponding ItemId
- One hash of QVariants on separate hash for each?
- Is LabelHash persistent. If so, can add a lot at once, like Xref, then parcel out to Buckets as needed.
- e.g., when importing ids. Then problem of conflicts.
- For now, a simple hash table. If sorted, it might compress better
-
-ThDisk::newItem -- tuple format for ItemId with aliases and various owned data
-
-Need to assign unique ItemId for Label in DepotId. By default use label hash (ylblhash). Unique in ThDisk.
-Retry n times, then unique in Depot by fewest hits.
-
- delitem -- All parts of an item
- itemblock -- diskblockid
- tgaliasid -- TopItemId for this alias
- tgaliases -- list of aliases for this itemId (moveitem fields to new TopItemId)
- if alias, someoneelse will own any text blocks, etc. (tgowned)
- remidcache -- In memory cache of itemid->diskBlockId
- delsig -- signature or conversion for itemId
- tgowned -- text, code, etc. with matchig howowned
- _adddel -- text blocks held onto for a while
- _addid -- resets xref itemid for text, xridcode, and xridtitle
- remdatas -- remove celldata for itemid
- item.-bucket -- Contains itemid's and label's to diskblockid by hashbucket
-
-ss:curcache
- itemid->blockid -- includes hash of label as itemid
-
-delsig convert.-routines
- ifconvert -- if Label is a typeid conversion from item
- delptr (tsisptr) -- isPointer signature (only one of type?)
- yupdstring(tsidlist) -- signature list
-
-block.sym
- fifieldid -- disk data
- tglabel -- type of disk data
-
-bkheld blocks -- in separete pool -- or separate list for each size as before
- itemid blocks
- text blocks
-
- m_unparsedTexts.insert(qMakePair(uri, encoding), result);
-
-
-====================================
-== Notes
-====================================
-
-protocol buffers
- wiretype 2, field 0, byte count for header
-
-====================================
-== Notes on git
-====================================
-
-Git
- Where to put the special value use sha1 convention
- how to check for all zero
-
-
-Check gitmailing list for messages titled "A note from the maintainer", "What's in
-git.git (stable)" and "What's cooking in git.git (topics)" and
-
-git verify-pack
- sha1 sorted -> type, size, offset, delta-base
- most are small! More than half are diffs. conpressed is larger for small diffs
- git a --depth clone for ghull
-
-git update-index
- --info-only is used to register files without placing them in the object database. This is useful for status-only repositories.
-
- git ls-files -s
- 100644 6569cf607b18b84f39ebee613471f270e42cfbdc 0 string-list.h
- 100644 3007f7d5a6279c14a7c29efdc752dbbc41218c76 0 submodule.c
- 100644 4c0269d67933659da5ff81e53c21b5f25ca8cf9d 0 submodule.h
- 100644 88601200114f857a57214a9bf0d02ffd39a83504 0 symlinks.c
- 100644 1b97c5465b7d9e4404e11668b44c5c507a302d4a 0 t/.gitattributes
- 100644 7dcbb232cd876cb7b976443cc586f60a94ab92bf 0 t/.gitignore
- 100644 bd09390d3208d7eac362cd9cf45f7dde623c4ae6 0 t/Makefile
- 100644 dcd3ebb5f2dcdbf15ca0e4a043b45cd2fc36cbb5 0 t/README
- 100755 d5bab75d7da49ebb53e368d67f6b867f5417a125 0 t/aggregate-results.sh
- 100644 396b9653a3ad80490cf360c86a910edff58862a2 0 t/annotate-tests.sh
-
-
-----------
-gitrepository-layout.html
-HowTo/maintain-git.txt -- what the branches mean
-git-rev-list -- identify commits and objects log and pack
-git-receive-pack -- works with git-send-pack and calls hooks sha1 sha2
-
-------------
-technical/pack-protocol.txt -- details of git pack transfer protocol
-
-technical/pack-format.txt -- where the bytes are. idx and pack files
-
-technical/pack-heuristics.txt -- how to create a pack and thin packs
-
- What is a "thin" pack?
-
- Use of --objects-edge to rev-list as the upstream of
- pack-objects. The pack transfer protocol negotiates that.
-
- - larger objects tend to be "more recent" (Linus' law: files grow)
- - we actively try to generate deltas from a larger object to a
- smaller one
- - this means that the top-of-tree very seldom has deltas
- (i.e. deltas in _practice_ are "backwards deltas")
-----
-git-notes.sh -- store notes for commits as a directory with sha1 filenames /refs/notes/sha1
-
-read-cache.c -- read and search the cache/index
- Can create an alias to an entry
- static struct cache_entry *create_alias_ce(struct cache_entry *ce, struct cache_entry *alias)
- reads cache/index into memory. Builds hash structure
-
----
-git/cache.h -- directory cache, comments
-
- file status, sha1, name
- ...
- TREE sha1 of corresponding tree object
- sha1 of index
-
- gitlink -- a submodule
- add_name_hash -- name index in cache
- OBJ_COMMIT = 1,
- OBJ_TREE = 2,
- OBJ_BLOB = 3,
- OBJ_TAG = 4,
- /* 5 for future expansion */
- OBJ_OFS_DELTA = 6,
- OBJ_REF_DELTA = 7,
-
- # Gitlink is a commit
- S_ISGITLINK(mode) ? OBJ_COMMIT :
- # Cache used in multiple environments?
- #define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
-#define REFRESH_IGNORE_SUBMODULES 0x0010 /* ignore submodules */
-static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
-struct ref {
- struct ref *next;
- unsigned char old_sha1[20];
- unsigned char new_sha1[20];
- char *symref;
-extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags, struct extra_have_objects *);
-
-git-apply a patch
-git-remote - manage set of tracked repositories
-
-git-clone
---shared
--s
-When the repository to clone is on the local machine, instead of using hard links, automatically setup .git/objects/info/alternates to share the objects with the source repository. The resulting repository starts out without any object of its own.
-
-config()
-core.gitProxy
-
-====================================
-== Thid Design, To Do, and Programming Style
-====================================
-
-[Feb 2008]
-
-does a Field know its type? It ought to, though can always look it up. The later avoids two type systems, conversion and consistency
-
-use QMetaType as the type system, it's just names, but ties into QVariant
-
-Want value semantics, owner semantics
-
-Should a field name be a thid? Can then call it what you will
-
-ItemReference.toName()
-
-Implemenetation ideas
- Staircase Join (used for XQuery)
-
-QMap
-Thid
- context, number handle, rev desc
- => flags, name, thidformat, handle
- immutable, appendable, ordered, mutable, mastership
-
-QMap
-ThField
- context, name handle, date desc
- => value handle, op, flags
- Vesta op for singleton, set, merge
- Similar to QObject dynamic properties, string name, QVariant value
-
-QMap
-ThName
- context (namespace)
- string
- => flags
- includes absolute and relative dirpaths
- immutable
- QString name= ThString::stringForHandle(m_nameHandle);
-
-QMultiMap
-ThNumber
- int128 -- includes fingerprints
- => flags
-
-ThList
-QList
-
-ThHandleIndex
-QMultiHash
-
-ThStringIndex
-QMultiHash
-
-DeletedHandles
-QSet
-
-All data is cached in memory
-
-On disk
- ThidComponent stores ThField hierarchy down to thid values
- Split into mutable and immutable pieces
- Mutable is specific to a location, and may be replicated elsewhere
- Immutable is specific to the thid revision and may be replicated
- Appendable means Add only
- Set means add, del, set
-
-1. Data in memory
-2. Read all data from disk
-3. Flush unused data -- fairly expensive, at the thid level
-
-Vesta has mutable attributes only if context is mutable
-
-not applicable
- Not xref value=>handles -- containing handles instead of actual
-
-vesta
- Vesta does attributes by shortid,name,value, add,del,datetime -- has advantage that handle never goes out of date, and easily merged. One advantage of handles is for hierarchical structure. can have a value and sub-values.
-
- VMemPool -- packed objects == thhandle
- VestaSource -- base type == thid
- VestaAttribs -- attributes of a VestaSource
- Val.H -- any SDL value, including bindings (BindVC)
-
-th add sdfA3_2007.rtf
-th get sadA*
-
-want to add a topic file with ids and titles
-a biblio file with entries
-memory-based id/file
-memory-based id/titles
-memory-based xref
-disk-based id/file
-disk-based xref
-disk-based id/titles/owner -- a form of xref
-network-based id/file
-network-based id/titles
-network-based xref
-a depot indexes all of its content
-all servers index all of their content
-
-change type tag to a char[4]
-Need recent list
-Work list editor, based on ListView
-Work list and item list accelerators
-Aliased items
-Condensed view
-Paragraph view
-Line editor
-Tree editor
-Add all data to expanded view (e.g., thid ID)
-Search by thid
-Logging -- multi-level
-Error handling
-Gprof
-Performance counters
-Versioning
-Remote access
-Merging
-Pointer machine
-CppCastingHelper -- in xml/query/util
-PlainSharedPtr -- never does a deref
-
-port logging model to Qt
-index="" for topics in nodes-dump.xml
-title= replaces element name
-attributes are tool tip
-TitleOf is all item-title elements of 'root'
-ContentOf is contents of item-def
-fix scroll of content
-
-====================================
-== thnode parser
-====================================
-
-Problems
- -- Record bad files with sufficient state to analyze, then skip
- -- unstructured text
- -- \b in a .Title or a \i in a .J -- should be an error, need to continue
- -- a blank indented line \li333 \
- -- illegal markup
- ;;2343 ;;@asdfsf asdfsdf
-
- not closed properly, see nodes.xml
- not formated properly, see nodes.xml
-
-====================================
-== C++ Style conventions for Thid
-====================================
-
-
-Append '_' to distinguish parameter names from member names
-Use all lower-case, abbreviated for local declarations and parameters declared at top. They act as pronoun references.
-Use camel-case for class components.
-Use initial caps for class names
-Define all entities as const by default
-All blocks defined by {...} -- if () x=1; is illegal
-Use Stroustrop formatting
-Set local variables instead of building a long expression
- ThItemModel model = db.getModel();
- mainwin.setSourceModel(model);
-vs.
- mainwin.setSourceModel(db.getModel());
-
- : modelSource(source), curThid(ThLocalID_null)
- , thidList(db->listForModelSourcedb())
-"explicit" means a non-converting constructor with one argument
-Place static strucs, fields, and methods last
-On whether to use nsFoo aFoo (bFoo) or nsFoo aFoo = bFoo: everyone agrees, the form with "=" looks better
-
-From Cwalina, K., Abrams, B., Framework Design Guidelines, 2006
-Use camel casing for all parameters
-Use PascalCase for all public IDs
-Only capitalize two-letter acroynms (e.g., IOFile)
-No public fields, use properties instead.
-Use m_ and s_ for fields and static fields (J. Richter)
-No underscores, hyphens, etc.
-Enumerations -- use plural names for bit fields (e.g., ConsoleModifiers), otherwise use singular names. Do not use Enum, Flag, or Flags suffixes, do not give enums a common prefix
-Try boolean predicates in an if statement, e.g., if(collection.Contains(item) vs. IsContained(item)
-add... -- append, insert, or otherwise add something to a collection
-
-QObject (e.g., QScriptEngine)
-QSharedData (e.g., QHash)
-Q_DISABLE_COPY frequently used, e.g., QTokenizer
-private d pointer to private data (e.g., QTestData)
-q pointer back to public, e.g., QObject
-public members in private data
-class with private data using m_...
-static data with s_....
-
-class ThidInfo {
- friend class ThidInfoPrivate;
-
- ThidInfoPrivate *d;
-
-//== class variables
-
-public:
-//== constants
- static const QString Separator;
- enum ThidFormat : char {
- NoFormat=0
- };
-
-//== constructor, destructor
-//== conversion
-//== accessor
-//== predicate
-//== mutator
-//== class function
-
-};//ThidInfo
-
-===============================
-== qHash for QHash
-===============================
-Dropped jul'11
-
-uint
-qHash(Thesa::Thid *t)
-{
- return qHash(t->thidIdentifier());
-};//qHash
-
-
-===============================
-== #pragma message(Remind "abc" )
-===============================
-//! Add fixup error log
-//! Windows Developer Journal, 197?)
-//! Alan De Smet -- Microsoft Visual C++ Tips and Tricks
-
-#ifndef Q_MOC_RUN
-#define Stringize( L ) #L
-#define MakeString( M, L ) M(L)
-#define MyLine MakeString( Stringize, __LINE__ )
-#define Fixup __FILE__ "(" MyLine ") : warning C1111: FIXUP "
-#pragma message(Remind "abc" )
-#endif
-// Can not define 'fixup' as #pragma
-
-
-
-void ThDiskBlock::
-setBlockOwner(const ThidIdentifier &depot, const ThidIdentifier &thid, HowId how)
-{
- if(how!=NoHow && how!=HowInvalid){
- ThFlagsInt code= how&HowCodeMask;
- if(code==0){
- throw ThError(10069, "ThDiskBlock: can not set howOwned to special code %u. Expecting NoHow(0) or HowInvalid(0x10000000)", 0,0,0.0, quint64(how));
- }
- if(code!=HowItemBucket){
- if(how&~HowCodeMask){
- throw ThError(10070, "ThDiskBlock: extra bits (0xFFFFFF00) set for howOwned %u", 0,0,0.0, quint64(how));
- }
- if((code>HowMaxSpecial && codeHowMaxOwned){
- throw ThError(10071, "ThDiskBlock: unknown code for setHowOwned %u. Expecting 0..9 or 0x60..62", 0,0,0.0, quint64(how));
- }
- }
- }
- owner_depot= depot;
- owner_thid= thid;
- how_owned= how;
-}//setBlockOwner
-
-============================================
-== DevStudio debugger
-============================================
-
-Alan De Smet's suggestions
- Workspace Whiz
- #pragma message(Reminder, "text")
- Resource Leaks: Detecting, Locating, and Repairing your leaky GDI code
- Watch window: @err or @err,hr for GetLastError and HRESULT
- p,10 shows 10 elements at p
-
- Debugging:
- __asm int 3; or __debugbreak (Common Expression Evaluator)
- Watches
- @clk ... @clk=0 Show and reset value of clock
- QuickWatch window
- Execute functions e.g., dumpT(p) which calls OutputDebugString or printf
- SetThreadName
- @tib+24 is the Thread ID (thread information block)
- set "Microsoft C++ Exception" to Stop Always (Debug > Exceptions)
- Breakpoints
- on argument value (condition dw esp+0x8==3) where 0x8 is the arg offset
- Avoid the very slow emulation mode -- no expressions
- 4 hardware data breakpoints -- may be triggered by process swap requiring a reboot
- Set breakpoint count to large value. Get actual count at crash. Break just before.
- Use breakpoint by name to handle edits
- Casts need exact type name (watch variable then look in properties)
- For pObject local while CMyClass defined in foo.dll
- {,,foo.dll}(CMyClass *){*}pObject
- Disassembly
- ^G EIP -- Goes to current location
-
-
-Through the Interface: Advanced Visual Studio debugging... July 24, 2006
- Or HKEY_LOCAL/Software/MS/VS/8.0/Native/StepOver
- autoexp.dat in devstudio/Common7/Packages/Debugger
- [ExecutionControl]
- CString::CString=NoStepInto # skips CString constructor
- CString::CString::operator==NoStepInto # skips CString::operator=
- CString::*=NoStepInto # skips all of CString
- At most 256 characters
- No multi-line output
- Can develop an AddIn for more complex displays
- $ADDIN -- Customizing the Visual Studio Debugger Display of Your Data (msdn aa730838 and 8fwk67y3)
- Very Advanced Debugging Tips
- Load debug symbols (see blogs.msdn/calvin_hsia/... 246382
- Register Window -- set Show Effecive Address)
- Common Expression...
- Add /MAP to LINK for full decorated names
-
- Writing custom visualizers for Visual Studio 2005 [blog.csdn.net/wilton]
- Match templates with type. Template parameters are $T1, $T2
- Match multiple types with Foo|Bar
- Preview must be one line. Use #(...) for a comma list of expressions using $c
- Preview sizeof() does not work.
- Avoid using colon, paren, brackets within strings and character literals
- The children block shows a sorted list (+[*]), optionally named with name:expr
- Names may have brackets
- Add sub-blocks by referencing an object with a visualizer
- Array expression [$c.start, 4c]
- Show all fields [$c,!] without autoexpand or visualizers
- #array with expr w/ $i, size, base w/o $e formating (offset), rank $r (multi-D).
- Follow #array with value autoexpander #array(..):&$e where $e is *expr
- Can be anything (except for #if)
- #if () (...) #elif (..) #else (..)
- #switch () #case 0x000 (...) #case ... #default (...) Do not use #array
- #list ( head: $c.head, next: nextNode, skip:stop-here, size:max-count):display-expression with $e
- #tree ( head: $c head, left: leftNode, right: rightNode, size: max-count, skip: stop-here ),
- The stringview block displays a modal text, xml, or html visualizer.
- No literal string in value expressions. Can't escape HTML
-
- Display code ,su is string in quotes. ,sub is string w/o quotes
-
- HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\UserDebuggerHotKey registry key. Modifying this you can set the keycode (scancode) that is registered as a global hotkey for the debugger. By default it's value is zero (0x0, F12), but you can set it to eg. 0x2F (VK_HELP)
-
-
-----
-EOF
-
diff --git a/html/qh-code.htm b/html/qh-code.htm
index 25ea608..4141718 100644
--- a/html/qh-code.htm
+++ b/html/qh-code.htm
@@ -1,954 +1,954 @@
Qhull code
Up: Home page for Qhull
Up: Qhull manual: Table of
Contents
To: Programs
Options
Output
Formats
Geomview
Print
Qhull
Precision
Trace
To: Qhull code: Table of Contents
(please wait while loading)
Dn: Qhull functions, macros, and data
structures
Qhull code
This section discusses the code for Qhull.
Copyright © 1995-2012 C.B. Barber
Empirically, Qhull's performance is balanced in the sense that
the average case happens on average. This may always be true if
the precision of the input is limited to at most O(log n)
bits. Empirically, the maximum number of vertices occurs at the
end of constructing the hull.
Let n be the number of input points, v be the
number of output vertices, and f_v be the maximum number
of facets for a convex hull of v vertices. If both
conditions hold, Qhull runs in O(n log v) in 2-d and 3-d
and O(n f_v/v) otherwise. The function f_v
increases rapidly with dimension. It is O(v^floor(d/2) /
floor(d/2)!).
The time complexity for merging is unknown. Options 'C-0' and 'Qx'
(defaults) handle precision problems due to floating-point
arithmetic. They are optimized for simplicial outputs.
When running large data sets, you should monitor Qhull's
performance with the 'TFn' option.
The time per facet is approximately constant. In high-d with many
merged facets, the size of the ridge sets grows rapidly. For
example the product of 8-d simplices contains 18 facets and
500,000 ridges. This will increase the time needed per facet.
As dimension increases, the number of facets and ridges in a
convex hull grows rapidly for the same number of vertices. For
example, the convex hull of 300 cospherical points in 6-d has
30,000 facets.
If Qhull appears to stop processing facets, check the memory
usage of Qhull. If more than 5-10% of Qhull is in virtual memory,
its performance will degrade rapidly.
When building hulls in 20-d and higher, you can follow the
progress of Qhull with option 'T1'.
It reports each major event in processing a point.
To reduce memory requirements, recompile Qhull for
single-precision reals (REALfloat in user.h).
Single-precision does not work with joggle ('QJ'). Check qh_MEMalign in user.h
and the match between free list sizes and data structure sizes
(see the end of the statistics report from 'Ts'). If free list sizes do not match,
you may be able to use a smaller qh_MEMalign. Setting
qh_COMPUTEfurthest saves a small amount of memory, as does
clearing qh_MAXoutside (both in user.h).
Shewchuk is working on a 3-d version of his triangle
program. It is optimized for 3-d simplicial Delaunay triangulation
and uses less memory than Qhull.
To reduce the size of the Qhull executable, consider
qh_NOtrace and qh_KEEPstatistics 0 in user.h. By
changing user.c you can also remove the input/output
code in io.c. If you don't need facet merging, then
version 1.01 of Qhull is much smaller. It contains some bugs that
prevent Qhull from initializing in simple test cases. It is
slower in high dimensions.
The precision options, 'Vn', 'Wn', 'Un'.
'A-n', 'C-n',
'An', 'Cn',
and 'Qx', may have large effects on
Qhull performance. You will need to experiment to find the best
combination for your application.
The verify option ('Tv') checks
every point after the hull is complete. If facet merging is used,
it checks that every point is inside every facet. This can take a
very long time if there are many points and many facets. You can
interrupt the verify without losing your output. If facet merging
is not used and there are many points and facets, Qhull uses a
directed search instead of an exhaustive search. This should be
fast enough for most point sets. Directed search is not used for
facet merging because directed search was already used for
updating the facets' outer planes.
The check-frequently option ('Tc')
becomes expensive as the dimension increases. The verify option
('Tv') performs many of the same
checks before outputting the results.
Options 'Q0' (no pre-merging), 'Q3' (no checks for redundant vertices),
'Q5' (no updates for outer planes),
and 'Q8' (no near-interior points)
increase Qhull's speed. The corresponding operations may not be
needed in your application.
In 2-d and 3-d, a partial hull may be faster to produce.
Option 'QgGn' only builds facets
visible to point n. Option 'QgVn'
only builds facets that contain point n. In higher-dimensions,
this does not reduce the number of facets.
User.h includes a number of performance-related
constants. Changes may improve Qhull performance on your data
sets. To understand their effect on performance, you will need to
read the corresponding code.
GNU gprof reports that the dominate cost for 3-d
convex hull of cosperical points is qh_distplane(), mainly called
from qh_findbestnew(). The dominate cost for 3-d Delaunay triangulation
is creating new facets in qh_addpoint(), while qh_distplane() remains
the most expensive function.
Warning: The C++ interface to Qhull is new and
incomplete. You will need to extend the interface for all
but the simplest applications.
You will need to understand the data structures and read the code.
Most users will find it easier to call Qhull as a program.
Note: Please download the 'next' branch from
git://gitorious.org/qhull/qhull.git
Qhull's C++ interface provides wrapper classes for Qhull and Rbox. It provides access to Qhull's data structures.
Most of the classes derive from the corresponding qhull data structure.
For example, QhullFacet is an instance of Qhull's facetT.
The main methods are
-
RboxPoints.appendRandomPoints
-- append random points according to rbox options.
-
Qhull.runQhull
-- construct the convex hull of the input points
-
Qhull.outputQhull
-- write output according to Qhull options
The sample program,
user_eg3.cpp, duplicates Qhull's facet dump (option 'f').
Example (c.f., user_eg3 eg-100
)
RboxPoints rbox;
rbox.appendRandomPoints("100");
Qhull qhull;
qhull.runQhull("", rbox);
QhullFacetList facets(qhull);
cout<< facets;
The C++ iterface for RboxPoints redefines the fprintf() calls
in rboxlib.c. Instead of writing its output to stdout, RboxPoints appends
the output to a std::vector.
The same technique may be used for calling Qhull from C++.
-
Run Qhull with option 'Ta' to annotate the
output with qh_fprintf() identifiers.
-
Redefine qh_fprintf() for these identifiers.
-
See RboxPoints.cpp for an example.
A more flexible approach extends Qhull's classes. For example,
to access the vertices of a QhullFacet,
define a constructor of QhullVertexSet
that takes a QhullFacet as a parameter.
With care, you may create multiple Qhull instances, but only one thread may use qh_qh,
qh_qhstat, and qhmem at a time (i.e., most of libqhull, the original C program).
only one instance may be active at time. The global pointer qh_qh
points to Qhull's data structure, QhullQh. The class
UsingLibQhull checks that qh_qh is correct.
Qhull objects have the entire qhull data structure, so they can explore this data structure independent of
libqhull. You can use any method that does not refer to UsingLibQhull, or invoke methods that refer to UsingLibQhull.
You may also use any method in libqhull that does not reference qh_qh, qh_qhstat (i.e., does not include the macro 'qh',
zinc_, etc) and does not allocate or deallocate memory via mem.c.
In particular, you can call most of the qset macros and functions, allowing you to explore the data structure
with 'foreachFacet_(), etc.' You can call all of the qset.h functions if you turn off Qhull's memory manager (qh_NOmem in mem.h)
Developing C++ code requires many conventions, idioms, and technical details.
The following questions have either
mystified the author or do not have a clear answer. See also
C++ and Perl Guidelines,
C++ interface to Qhull. and FIXUP
in the code. Please add notes to Gitorious wiki.
A CoordinateIterator or ConstCoordinateIterator [RboxPoints.cpp] is a std::vector<realT>::iterator
for Rbox and Qhull coordinates.
It is the result type of RboxPoints.coordinates().
Qhull does not use CoordinateIterator for its data structures. A point in Qhull is an array of reals instead of a std::vector.
See QhullPoint.
Qhull is the top-level class for running Qhull.
It initializes Qhull, runs the computation, and records errors.
It provides access to the global data structure QhullQh,
Qhull's facets, and vertices.
QhullError is derived from std::exception
. It reports errors from Qhull and captures the output to stderr.
If error handling is not set up, Qhull exits with a code from 1 to 5
[qh_ERR* in libqhull.h via qh_exit() in usermem.c]. The C++ interface does not report the
captured output in QhullError. Call Qhull::setErrorStream to send output to cerr instead.
A QhullFacet is a facet of the convex hull, a region of the Delaunay triangulation, a vertex of a Voronoi diagram,
or an intersection of the halfspace intersection about a point.
A QhullFacet has a set of QhullVertex, a set of QhullRidge, and
a set of neighboring QhullFacets.
A QhullFacetList is a linked list of QhullFacet. The result of Qhull.runQhull
is a QhullFacetList stored
in QhullQh.
A QhullFacetSet is a QhullSet of QhullFacet. QhullFacetSet may be ordered or unordered. The neighboring facets of a QhullFacet is a QhullFacetSet.
The neighbors of a QhullFacet is a QhullFacetSet.
The neighbors are ordered for simplicial facets, matching the opposite vertex of the facet.
QhullIterator contains macros for defining Java-style iterator templates from a STL-style iterator template.
A QhullLinkedLIst is a template for linked lists with next and previous pointers.
QhullFacetList and QhullVertexList are QhullLinkedLists.
A QhullPoint is an array of point coordinates, typically doubles. The length of the array is QhullQh.hull_dim.
The identifier of a QhullPoint is its 0-based index from QhullQh.first_point followed by QhullQh.other_points.
A QhullPointSet is a QhullSet of QhullPoint. The QhullPointSet of a QhullFacet is its coplanar points.
QhullQh is the root of Qhull's data structure.
It contains initialized constants, sets, buffers, and variables.
It contains an array and a set of QhullPoint,
a list of QhullFacet, and a list of QhullVertex.
The points are the input to Qhull. The facets and vertices are the result of running Qhull.
Qhull's functions access QhullQh through the global variable, qh_qh
.
The global data structures, qh_stat and qh_mem, record statistics and manage memory respectively.
A QhullRidge represents the edge between two QhullFacet's.
It is always simplicial with qh.hull_dim-1 QhullVertex)'s.
A QhullRidgeSet is a QhullSet of QhullRidge. Each QhullFacet contains a QhullRidgeSet.
A QhullSet is a set of pointers to objects. QhullSets may be ordered or unordered. They are the core data structure for Qhull.
A QhullVertex is a vertex of the convex hull. A simplicial QhullFacet has qh.hull_dim-1 vertices. A QhullVertex contains a QhullPoint.
It may list its neighboring QhullFacet's.
A QhullVertexList is a QhullLinkedList of QhullVertex.
The global data structure, QhullQh contains a QhullVertexList of all
the vertices.
A QhullVertexSet is a QhullSet of QhullVertex.
The QhullVertexSet of a QhullFacet is the vertices of the facet. It is
ordered for simplicial facets and unordered for non-simplicial facets.
RboxPoints is a std::vector of point coordinates (QhullPoint).
It's iterator is CoordinateIterator.
RboxPoints.appendRandomPoints()
appends points from a variety of distributions such as uniformly distributed within a cube and random points on a sphere.
It can also append a cube's vertices or specific points.
UsingLibQhull checks that the current thread owns Qhull's global data structure, QhullQh.
It is required while calling the Qhull library. Otherwise two threads may be updating and reading the same data structure.
Warning: Qhull was not designed for calling from C
programs. You may find the C++ interface easier to use.
You will need to understand the data structures and read the code.
Most users will find it easier to call Qhull as an external
command.
For examples of calling Qhull, see GNU Octave's
computational geometry code,
and Qhull's
user_eg.c,
user_eg2.c, and
user.c. To see how Qhull calls its library, read
unix.c,
qconvex.c,
qdelaun.c,
qhalf.c, and
qvoronoi.c.
The BGL
Boost Graph Library [aka GGCL] provides C++ classes for graph data structures
and algorithms [Dr. Dobb's 9/00 p. 29-38; OOPSLA '99 p. 399-414]. It is modelled after the
Standard Template Library. It would provide a good interface to Qhull.
If you are interested in adapting BGL to Qhull, please contact
bradb@shore.net.
See Qhull functions, macros, and data
structures for internal documentation of Qhull. The
documentation provides an overview and index. To use the library
you will need to read and understand the code. For most users, it
is better to write data to a file, call the qhull program, and
read the results from the output file.
When you read the code, be aware of the macros "qh"
and "qhstat", e.g., "qh hull_dim". They are
defined in libqhull.h. They allow the global data
structures to be pre-allocated (faster access) or dynamically
allocated (allows multiple copies).
Qhull's Makefile produces a library, libqhull.a,
for inclusion in your programs. First review libqhull.h.
This defines the data structures used by Qhull and provides
prototypes for the top-level functions.
Most users will only need libqhull.h in their programs. For
example, the Qhull program is defined with libqhull.h and unix.c.
To access all functions, use qhull_a.h. Include the file
-with "#include <qhull/qhull_a.h>". This
+with "#include <libqhull/qhull_a.h>". This
avoids potential name conflicts.
If you use the Qhull library, you are on your own as far as
bugs go. Start with small examples for which you know the output.
If you get a bug, try to duplicate it with the Qhull program. The
'Tc' option will catch many problems
as they occur. When an error occurs, use 'T4 TPn'
to trace from the last point added to the hull. Compare your
trace with the trace output from the Qhull program.
Errors in the Qhull library are more likely than errors in the
Qhull program. These are usually due to feature interactions that
do not occur in the Qhull program. Please report all errors that
you find in the Qhull library. Please include suggestions for
improvement.
You can use mem.c and qset.c individually. Mem.c
implements quick-fit memory allocation. It is faster than
malloc/free in applications that allocate and deallocate lots of
memory.
Qset.c implements sets and related collections. It's
the inner loop of Qhull, so speed is more important than
abstraction. Set iteration is particularly fast. qset.c
just includes the functions needed for Qhull.
Here some unchecked code to print the point indices of each
Delaunay triangle. Use option 'QJ' if you want to avoid
non-simplicial facets. Note that upper Delaunay regions are
skipped. These facets correspond to the furthest-site Delaunay
triangulation.
facetT *facet;
vertexT *vertex, **vertexp;
FORALLfacets {
if (!facet->upperdelaunay) {
printf ("%d", qh_setsize (facet->vertices);
FOREACHvertex_(facet->vertices)
printf (" %d", qh_pointid (vertex->point));
printf ("\n");
}
}
The routine qh_findbestfacet in poly2.c is
particularly useful. It uses a directed search to locate the
facet that is furthest below a point. For Delaunay
triangulations, this facet is the Delaunay triangle that contains
the lifted point. For convex hulls, the distance of a point to
the convex hull is either the distance to this facet or the
distance to a subface of the facet.
Warning: If triangulated output ('Qt') and
the best facet is triangulated, qh_findbestfacet() returns one of
the corresponding 'tricoplanar' facets. The actual best facet may be a different
tricoplanar facet.
See qh_nearvertex() in poly2.c for sample code to visit each
tricoplanar facet. To identify the correct tricoplanar facet,
see Devillers, et. al., ['01]
and Mucke, et al ['96]. If you
implement this test in general dimension, please notify
qhull@qhull.org.
qh_findbestfacet performs an exhaustive search if its directed
search returns a facet that is above the point. This occurs when
the point is inside the hull or if the curvature of the convex
hull is less than the curvature of a sphere centered at the point
(e.g., a point near a lens-shaped convex hull). When the later
occurs, the distance function is bimodal and a directed search
may return a facet on the far side of the convex hull.
Algorithms that retain the previously constructed hulls
usually avoid an exhaustive search for the best facet. You may
use a hierarchical decomposition of the convex hull [Dobkin and
Kirkpatrick '90].
To use qh_findbestfacet with Delaunay triangulations, lift the
point to a paraboloid by summing the squares of its coordinates
(see qh_setdelaunay in geom2.c). Do not scale the input with
options 'Qbk', 'QBk', 'QbB' or 'Qbb'. See Mucke, et al ['96] for a good point location
algorithm.
The intersection of a ray with the convex hull may be found by
locating the facet closest to a distant point on the ray.
Intersecting the ray with the facet's hyperplane gives a new
point to test.
The Qhull library may be used for the on-line construction of
convex hulls, Delaunay triangulations, and halfspace
intersections about a point. It may be slower than implementations that retain
intermediate convex hulls (e.g., Clarkson's hull
program). These implementations always use a directed search.
For the on-line construction of convex hulls and halfspace
intersections, Qhull may use an exhaustive search
(qh_findbestfacet).
You may use qh_findbestfacet and qh_addpoint (libqhull.c) to add a point to
a convex hull. Do not modify the point's coordinates since
qh_addpoint does not make a copy of the coordinates. For Delaunay
triangulations, you need to lift the point to a paraboloid by
summing the squares of the coordinates (see qh_setdelaunay in
geom2.c). Do not scale the input with options 'Qbk', 'QBk', 'QbB'
or 'Qbb'. Do not deallocate the point's coordinates. You need to
provide a facet that is below the point (qh_findbestfacet).
You can not delete points. Another limitation is that Qhull
uses the initial set of points to determine the maximum roundoff
error (via the upper and lower bounds for each coordinate).
For many applications, it is better to rebuild the hull from
scratch for each new point. This is especially true if the point
set is small or if many points are added at a time.
Calling qh_addpoint from your program may be slower than
recomputing the convex hull with qh_qhull. This is especially
true if the added points are not appended to the qh first_point
array. In this case, Qhull must search a set to determine a
point's ID. [R. Weber]
See user_eg.c for examples of the on-line construction of
convex hulls, Delaunay triangulations, and halfspace
intersections. The outline is:
initialize qhull with an initial set of points
qh_qhull();
for each additional point p
append p to the end of the point array or allocate p separately
lift p to the paraboloid by calling qh_setdelaunay
facet= qh_findbestfacet (p, !qh_ALL, &bestdist, &isoutside);
if (isoutside)
if (!qh_addpoint (point, facet, False))
break; /* user requested an early exit with 'TVn' or 'TCn' */
call qh_check_maxout() to compute outer planes
terminate qhull
With a fair amount of work, Qhull is suitable for constrained
Delaunay triangulation. See Shewchuk, ACM Symposium on
Computational Geometry, Minneapolis 1998.
Here's a quick way to add a constraint to a Delaunay
triangulation: subdivide the constraint into pieces shorter than
the minimum feature separation. You will need an independent
check of the constraint in the output since the minimum feature
separation may be incorrect. [H. Geron]
Option 'Qt' triangulates non-simplicial
facets (e.g., a square facet in 3-d or a cubical facet in 4-d).
All facets share the same apex (i.e., the first vertex in facet->vertices).
For each triangulated facet, Qhull
sets facet->tricoplanar true and copies facet->center, facet->normal, facet->offset, and facet->maxoutside. One of
the facets owns facet->normal; its facet->keepcentrum is true.
If facet->isarea is false, facet->triowner points to the owning
facet.
Qhull sets facet->degenerate if the facet's vertices belong
to the same ridge of the non-simplicial facet.
To visit each tricoplanar facet of a non-simplicial facet,
either visit all neighbors of the apex or recursively visit
all neighbors of a tricoplanar facet. The tricoplanar facets
will have the same facet->center.
See qh_detvridge for an example of ignoring tricoplanar facets.
The following code iterates over all Voronoi vertices for each
Voronoi region. Qhull computes Voronoi vertices from the convex
hull that corresponds to a Delaunay triangulation. An input site
corresponds to a vertex of the convex hull and a Voronoi vertex
corresponds to an adjacent facet. A facet is
"upperdelaunay" if it corresponds to a Voronoi vertex
"at-infinity". Qhull uses qh_printvoronoi in io.c
for 'qvoronoi o'
/* please review this code for correctness */
qh_setvoronoi_all();
FORALLvertices {
site_id = qh_pointid (vertex->point);
if (qh hull_dim == 3)
qh_order_vertexneighbors(vertex);
infinity_seen = 0;
FOREACHneighbor_(vertex) {
if (neighbor->upperdelaunay) {
if (!infinity_seen) {
infinity_seen = 1;
... process a Voronoi vertex "at infinity" ...
}
}else {
voronoi_vertex = neighbor->center;
... your code goes here ...
}
}
}
Qhull uses qh_printvdiagram() in io.c to print the ridges of a
Voronoi diagram for option 'Fv'.
The helper function qh_eachvoronoi() does the real work. It calls
the callback 'printvridge' for each ridge of the Voronoi diagram.
You may call qh_printvdiagram2(), qh_eachvoronoi(), or
qh_eachvoronoi_all() with your own function. If you do not need
the total number of ridges, you can skip the first call to
qh_printvdiagram2(). See qh_printvridge() and qh_printvnorm() in
io.c for examples.
To visit all of the vertices that share an edge with a vertex:
- Generate neighbors for each vertex with
qh_vertexneighbors in poly2.c.
- For simplicial facets, visit the vertices of each
neighbor
- For non-simplicial facets,
- Generate ridges for neighbors with qh_makeridges
in merge.c.
- Generate ridges for a vertex with qh_vertexridges
in merge.c.
- Visit the vertices of these ridges.
For non-simplicial facets, the ridges form a simplicial
decomposition of the (d-2)-faces between each pair of facets --
if you need 1-faces, you probably need to generate the full face
graph of the convex hull.
There are many ways in which Qhull can be improved.
[Jan 2010] Suggestions
- Generate vcproj from qtpro files
cd qtpro && qmake -spec win32-msvc2005 -tp vc -recursive
sed -i 's/C\:\/bash\/local\/qhull\/qtpro\///' qhull-all.sln
Change qhullcpp to libqhull.dll
Allow both builds on same host (keep /tmp separate)
- Make distribution -- remove tmp, news, .git, leftovers from project, change CRLF
search for 2010.1, Dates
qhulltest --all added to output
Add md5sum
Add test of user_eg3, etc.
- C++ class for access to statistics, accumulate vs. add
- Add dialog box to RoadError-- a virtual function?
- Option 'Gt' does not make visible all facets of the mesh example, rbox 32 M1,0,1 | qhull d Gt
- Option to select bounded Voronoi regions [A. Uzunovic]
- Merge small volume boundary cells into unbounded regions [Dominik Szczerba]
- Postmerge with merge options
- Add const to C code
- Add modify operators and MutablePointCoordinateIterator to PointCoordinates
- Add Qtest::toString() functions for QhullPoint and others. QByteArray and qstrdup()
- Fix option Qt for conformant triangulations of merged facets
- Investigate flipped facet -- rbox 100 s D3 t1263080158 | qhull R1e-3 Tcv Qc
- Add doc comments to c++ code
- Measure performance of Qhull, seconds per point by dimension
- Report potential wraparound of 64-bit ints -- e.g., a large set or points
Documentation
- Qhull::addPoint(). Problems with qh_findbestfacet and otherpoints see
qh-code.htm#inc on-line construction with qh_addpoint()
- How to handle 64-bit possible loss of data. WARN64, ptr_intT, size_t/int
- Show custom of qh_fprintf
- grep 'qh_mem ' x | sort | awk '{ print $2; }' | uniq -c | grep -vE ' (2|4|6|8|10|12|14|16|20|64|162)[^0-9]'
- qtpro/qhulltest contains .pro and Makefile. Remove Makefiles by setting shadow directory to ../../tmp/projectname
- Rules for use of qh_qh and multi processes
UsingQhull
errorIfAnotherUser
~QhullPoints() needs ownership of qh_qh
Does !qh_pointer work?
When is qh_qh required? Minimize the time.
qhmem, qhstat.ferr
qhull_inuse==1 when qhull globals active [not useful?]
rbox_inuse==1 when rbox globals active
- Multithreaded -- call largest dimension for infinityPoint() and origin()
- Better documentation for qhmem totshort, freesize, etc.
- how to change .h, .c, and .cpp to text/html. OK in Opera
- QhullVertex.dimension() is not quite correct, epensive
- Check globalAngleEpsilon
- Deprecate save_qhull()
[Dec 2003] Here is a partial list:
- fix finddelaunay() in user_eg.c for tricoplanar facets
- write a BGL, C++ interface to Qhull
http://www.boost.org/libs/graph/doc/table_of_contents.html
- change qh_save_qhull to swap the qhT structure instead of using pointers
- change error handling and tracing to be independent of 'qh ferr'
- determine the maximum width for a given set of parameters
- prove that directed search locates all coplanar facets
- in high-d merging, can a loop of facets become disconnected?
- find a way to improve inner hulls in 5-d and higher
- determine the best policy for facet visibility ('Vn')
- determine the limitations of 'Qg'
Precision improvements:
- For 'Qt', resolve cross-linked, butterfly ridges.
May allow retriangulation in qh_addpoint().
- for Delaunay triangulations ('d' or 'v') under joggled input ('QJ'),
remove vertical facets whose lowest vertex may be coplanar with convex hull
- review use of 'Qbb' with 'd QJ'. Is MAXabs_coord better than MAXwidth?
- check Sugihara and Iri's better in-sphere test [Canadian
Conf. on Comp. Geo., 1989; Univ. of Tokyo RMI 89-05]
- replace centrum with center of mass and facet area
- handle numeric overflow in qh_normalize and elsewhere
- merge flipped facets into non-flipped neighbors.
currently they merge into best neighbor (appears ok)
- determine min norm for Cramer's rule (qh_sethyperplane_det). It looks high.
- improve facet width for very narrow distributions
New features:
- implement Matlab's tsearch() using Qhull
- compute volume of Voronoi regions. You need to determine the dual face
graph in all dimensions [see Clarkson's hull program]
- compute alpha shapes [see Clarkson's hull program]
- implement deletion of Delaunay vertices
see Devillers, ACM Symposium on Computational Geometry, Minneapolis 1999.
- compute largest empty circle [see O'Rourke, chapter 5.5.3] [Hase]
- list redundant (i.e., coincident) vertices [Spitz]
- implement Mucke, et al, ['96] for point location in Delaunay triangulations
- implement convex hull of moving points
- implement constrained Delaunay diagrams
see Shewchuk, ACM Symposium on Computational Geometry, Minneapolis 1998.
- estimate outer volume of hull
- automatically determine lower dimensional hulls
- allow "color" data for input points
need to insert a coordinate for Delaunay triangulations
Input/output improvements:
- Support the VTK Visualization Toolkit, http://www.kitware.com/vtk.html
- generate output data array for Qhull library [Gautier]
- need improved DOS window with screen fonts, scrollbar, cut/paste
- generate Geomview output for Voronoi ridges and unbounded rays
- generate Geomview output for halfspace intersection
- generate Geomview display of furthest-site Voronoi diagram
- use 'GDn' to view 5-d facets in 4-d
- convert Geomview output for other 3-d viewers
- add interactive output option to avoid recomputing a hull
- orient vertex neighbors for 'Fv' in 3-d and 2-d
- track total number of ridges for summary and logging
Performance improvements:
- optimize Qhull for 2-d Delaunay triangulations
- use O'Rourke's '94 vertex->duplicate_edge
- add bucketing
- better to specialize all of the code (ca. 2-3x faster w/o merging)
- use updated LU decomposition to speed up hyperplane construction
- [Gill et al. 1974, Math. Comp. 28:505-35]
- construct hyperplanes from the corresponding horizon/visible facets
- for merging in high d, do not use vertex->neighbors
Please let us know about your applications and improvements.
Up: Home
page for Qhull
Up: Qhull manual: Table of
Contents
To: Programs
Options
Output
Formats
Geomview
Print
Qhull
Precision
Trace
To: Qhull code: Table of Contents
Dn: Qhull functions, macros, and data
structures
The Geometry Center
Home Page
Comments to: qhull@qhull.org
Created: Sept. 25, 1995 --- Last modified: see changes.txt
diff --git a/html/qhalf.htm b/html/qhalf.htm
index ec88291..ef8b15f 100644
--- a/html/qhalf.htm
+++ b/html/qhalf.htm
@@ -1,597 +1,598 @@
qhalf -- halfspace intersection about a point
Up: Home page for Qhull
Up: Qhull manual: Table of Contents
To: Programs
Options
Output
Formats
Geomview
Print
Qhull
Precision
Trace
To: synopsis
input outputs
controls graphics
notes conventions
options
qhalf -- halfspace intersection about a point
The intersection of a set of halfspaces is a polytope. The
polytope may be unbounded. See Preparata & Shamos ['85] for a discussion. In low
dimensions, halfspace intersection may be used for linear
programming.
- Example: rbox c | qconvex FQ FV
n | qhalf Fp
- Print the intersection of the facets of a cube. rbox c
generates the vertices of a cube. qconvex FV n returns of average
of the cube's vertices (in this case, the origin) and the halfspaces
that define the cube. qhalf Fp computes the intersection of
the halfspaces about the origin. The intersection is the vertices
of the original cube.
Example: rbox c d G0.55 | qconvex FQ FV
n | qhalf Fp
- Print the intersection of the facets of a cube and a diamond. There
are 24 facets and 14 intersection points. Four facets define each diamond
vertex. Six facets define each cube vertex.
Example: rbox c d G0.55 | qconvex FQ FV
n | qhalf Fp
Qt
- Same as above except triangulate before computing
the intersection points. Three facets define each intersection
point. There are two duplicates of the diamond and four duplicates of the cube.
Qhull computes a halfspace intersection by the geometric
duality between points and halfspaces.
See halfspace examples,
qhalf notes, and
option 'p' of qhalf outputs.
By default, halfspace intersections may be defined by more than
d halfspaces. See the previous cube and diamond example.
This is the expected output for halfspace intersection.
You can try triangulated output and joggled input. It demonstrates
that triangulated output is more accurate than joggled input.
If you use 'Qt' (triangulated output), all
halfspace intersections are simplicial (e.g., three halfspaces per
intersection in 3-d). In 3-d, if more than three halfspaces intersect
at the same point, triangulated output will produce
duplicate intersections, one for each additional halfspace. See the previous
cube and diamond example.
If you use 'QJ' (joggled input), all halfspace
intersections are simplicial. This may lead to nearly identical
intersections. For example, replace 'Qt' with 'QJ' above and
compare the duplicated intersections.
See Merged facets or joggled input.
The 'qhalf' program is equivalent to
'qhull H' in 2-d to 4-d, and
'qhull H Qx'
in 5-d and higher. It disables the following Qhull
options: d n v Qbb QbB Qf Qg Qm
Qr QR Qv Qx Qz TR E V Fa FA FC FD FS Ft FV Gt Q0,etc.
Copyright © 1995-2012 C.B. Barber
qhalf- halfspace intersection about a point.
input (stdin): [dim, 1, interior point]
dim+1, n
halfspace coefficients + offset
comments start with a non-numeric character
options (qhalf.htm):
Hn,n - specify coordinates of interior point
Qt - triangulated output
QJ - joggle input instead of merging facets
Tv - verify result: structure, convexity, and redundancy
. - concise list of all options
- - one-line description of all options
output options (subset):
s - summary of results (default)
Fp - intersection coordinates
Fv - non-redundant halfspaces incident to each intersection
Fx - non-redundant halfspaces
o - OFF file format (dual convex hull)
G - Geomview output (dual convex hull)
m - Mathematica output (dual convex hull)
QVn - print intersections for halfspace n, -n if not
TO file - output results to file, may be enclosed in single quotes
examples:
rbox d | qconvex n | qhalf s H0,0,0 Fp
rbox c | qconvex FV n | qhalf s i
rbox c | qconvex FV n | qhalf s o
The input data on stdin consists of:
- [optional] interior point
- dimension
- 1
- coordinates of interior point
- dimension + 1
- number of halfspaces
- halfspace coefficients followed by offset
Use I/O redirection (e.g., qhalf < data.txt), a pipe (e.g., rbox c | qconvex FV n | qhalf),
or the 'TI' option (e.g., qhalf TI data.txt).
Qhull needs an interior point to compute the halfspace
-intersection. An interior point is inside all of the halfspaces Hx+b
-<= 0. The interior point may be in the input. If not, option
+intersection. An interior point is clearly inside all of the halfspaces.
+The interior point may be in the input. If not, option
'Hn,n' defines the interior point as
[n,n,0,...] where 0 is the default coordinate (e.g.,
'H0' is the origin). Use linear programming if you do not know
the interior point (see halfspace notes),
The input to qhalf is a set of halfspaces. Each halfspace is defined by
d coefficients followed by a signed offset. This defines
a linear inequality. The coefficients define a vector that is
normal to the halfspace. The vector may have any length. If it
has length one, the offset is the distance from the origin to the
-halfspace's boundary.
+halfspace's boundary. The distance from the interior point to each
+halfspace is negative.
-This is the same format used for output options 'The halfspace format is the same as Qhull's output options 'n', 'Fo',
and 'Fi'. Use option 'Fd' to use cdd format for the
halfspaces.
For example, here is the input for computing the intersection
of halfplanes that form a cube.
rbox c | qconvex FQ FV n TO data
RBOX c | QCONVEX FQ FV n
3 1
0 0 0
4
6
0 0 -1 -0.5
0 -1 0 -0.5
1 0 0 -0.5
-1 0 0 -0.5
0 1 0 -0.5
0 0 1 -0.5
qhalf s Fp < data
Halfspace intersection by the convex hull of 6 points in 3-d:
Number of halfspaces: 6
Number of non-redundant halfspaces: 6
Number of intersection points: 8
Statistics for: RBOX c | QCONVEX FQ FV n | QHALF s Fp
Number of points processed: 6
Number of hyperplanes created: 11
Number of distance tests for qhull: 11
Number of merged facets: 1
Number of distance tests for merging: 45
CPU seconds to compute hull (after input): 0
3
3
8
-0.5 0.5 0.5
0.5 0.5 0.5
-0.5 0.5 -0.5
0.5 0.5 -0.5
0.5 -0.5 0.5
-0.5 -0.5 0.5
-0.5 -0.5 -0.5
0.5 -0.5 -0.5
The following options control the output for halfspace
intersection.
-
- Intersections
- FN
- list intersection points for each non-redundant
halfspace. The first line
is the number of non-redundant halfspaces. Each remaining
lines starts with the number of intersection points. For the cube
example, each halfspace has four intersection points.
- Fn
- list neighboring intersections for each intersection point. The first line
is the number of intersection points. Each remaining line
starts with the number of neighboring intersections. For the cube
example, each intersection point has three neighboring intersections.
In 3-d, a non-simplicial intersection has more than three neighboring
intersections. Use option 'QJ' to
avoid non-simplicial intersections.
- Fp
- print intersection coordinates. The first line is the dimension and the
second line is the number of intersection points. The following lines are the
coordinates of each intersection.
- FI
- list intersection IDs. The first line is the number of
intersections. The IDs follow, one per line.
-
-
- Halfspaces
- Fx
- list non-redundant halfspaces. The first line is the number of
non-redundant halfspaces. The other lines list one halfspace per line.
A halfspace is non-redundant if it
defines a facet of the intersection. Redundant halfspaces are ignored. For
the cube example, all of the halfspaces are non-redundant.
- Fv
- list non-redundant halfspaces incident to each intersection point.
The first line is the number of
non-redundant halfspaces. Each remaining line starts with the number
of non-redundant halfspaces. For the
cube example, each intersection is incident to three halfspaces.
- i
- list non-redundant halfspaces incident to each intersection point. The first
line is the number of intersection points. Each remaining line
lists the incident, non-redundant halfspaces. For the
cube example, each intersection is incident to three halfspaces.
- Fc
- list coplanar halfspaces for each intersection point. The first line is
the number of intersection points. Each remaining line starts with
the number of coplanar halfspaces. A coplanar halfspace is listed for
one intersection point even though it is coplanar to multiple intersection
points.
- Qi Fc
- list redundant halfspaces for each intersection point. The first line is
the number of intersection points. Each remaining line starts with
the number of redundant halfspaces. Use options 'Qc Qi Fc' to list
coplanar and redundant halfspaces.
-
-
- General
- s
- print summary for the halfspace intersection. Use 'Fs' if you need numeric data.
- o
- print vertices and facets of the dual convex hull. The
first line is the dimension. The second line is the number of
vertices, facets, and ridges. The vertex
coordinates are next, followed by the facets, one per line.
- p
- print vertex coordinates of the dual convex hull. Each vertex corresponds
to a non-redundant halfspace. Its coordinates are the negative of the hyperplane's coefficients
divided by the offset plus the inner product of the coefficients and
the interior point (-c/(b+a.p).
Options 'p Qc' includes coplanar halfspaces.
Options 'p Qi' includes redundant halfspaces.
- m
- Mathematica output for the dual convex hull in 2-d or 3-d.
- FM
- Maple output for the dual convex hull in 2-d or 3-d.
- G
- Geomview output for the dual convex hull in 2-d, 3-d, or 4-d.
These options provide additional control:
- Qt
- triangulated output. If a 3-d intersection is defined by more than
three hyperplanes, Qhull produces duplicate intersections -- one for
each extra hyperplane.
- QJ
- joggle the input instead of merging facets. In 3-d, this guarantees that
each intersection is defined by three hyperplanes.
- f
- facet dump. Print the data structure for each intersection (i.e.,
facet)
- TFn
- report summary after constructing n
intersections
- QVn
- select intersection points for halfspace n
(marked 'good')
- QGn
- select intersection points that are visible to halfspace n
(marked 'good'). Use -n for the remainder.
- Qbk:0Bk:0
- remove the k-th coordinate from the input. This computes the
halfspace intersection in one lower dimension.
- Tv
- verify result
- TI file
- input data from file. The filename may not use spaces or quotes.
- TO file
- output results to file. Use single quotes if the filename
contains spaces (e.g., TO 'file with spaces.txt'
- Qs
- search all points for the initial simplex. If Qhull can
not construct an initial simplex, it reports a
descriptive message. Usually, the point set is degenerate and one
or more dimensions should be removed ('Qbk:0Bk:0').
If not, use option 'Qs'. It performs an exhaustive search for the
best initial simplex. This is expensive is high dimensions.
To view the results with Geomview, compute the convex hull of
the intersection points ('qhull FQ H0 Fp | qhull G'). See Halfspace examples.
See halfspace intersection for precision issues related to qhalf.
If you do not know an interior point for the halfspaces, use
linear programming to find one. Assume, n halfspaces
defined by: aj*x1+bj*x2+cj*x3+dj>=0, j=1..n. Perform
the following linear program:
max(x5) aj*x1+bj*x2+cj*x3+dj*x4-x5>=0, j=1..n
Then, if [x1,x2,x3,x4,x5] is an optimal solution with
x4,x5>0 we get:
aj*(x1/x4)+bj*(x2/x4)+cj*(x3/x4)+dj>=(x5/x4)>0,
j=1..n
and conclude that the point [x1/x4,x2/x4,x3/x4] is in
the interior of all the halfspaces. Note that x5 is
optimal, so this point is "way in" the interior (good
for precision errors).
After finding an interior point, the rest of the intersection
algorithm is from Preparata & Shamos ['85, p. 316, "A simple case
..."]. Translate the halfspaces so that the interior point
is the origin. Calculate the dual polytope. The dual polytope is
the convex hull of the vertices dual to the original faces in
regard to the unit sphere (i.e., halfspaces at distance d
from the origin are dual to vertices at distance 1/d).
Then calculate the resulting polytope, which is the dual of the
dual polytope, and translate the origin back to the interior
point [S. Spitz and S. Teller].
The following terminology is used for halfspace intersection
in Qhull. This is the hardest structure to understand. The
underlying structure is a convex hull with one vertex per
non-redundant halfspace. See convex hull
conventions and Qhull's data structures.
- interior point - a point in the intersection of
the halfspaces. Qhull needs an interior point to compute
the intersection. See halfspace input.
- halfspace - d coordinates for the
normal and a signed offset. The distance to an interior
point is negative.
- non-redundant halfspace - a halfspace that
defines an output facet
- vertex - a dual vertex in the convex hull
corresponding to a non-redundant halfspace
- coplanar point - the dual point corresponding to
a similar halfspace
- interior point - the dual point corresponding to
a redundant halfspace
- intersection point- the intersection of d
or more non-redundant halfspaces
- facet - a dual facet in the convex hull
corresponding to an intersection point
- non-simplicial facet - more than d
halfspaces intersect at a point
- good facet - an intersection point that
satisfies restriction 'QVn',
etc.
qhalf- compute the intersection of halfspaces about a point
http://www.qhull.org
input (stdin):
optional interior point: dimension, 1, coordinates
first lines: dimension+1 and number of halfspaces
other lines: halfspace coefficients followed by offset
comments: start with a non-numeric character
options:
Hn,n - specify coordinates of interior point
Qt - triangulated ouput
QJ - joggle input instead of merging facets
Qc - keep coplanar halfspaces
Qi - keep other redundant halfspaces
Qhull control options:
QJn - randomly joggle input in range [-n,n]
Qbk:0Bk:0 - remove k-th coordinate from input
Qs - search all halfspaces for the initial simplex
QGn - print intersection if redundant to halfspace n, -n for not
QVn - print intersections for halfspace n, -n if not
Trace options:
T4 - trace at level n, 4=all, 5=mem/gauss, -1= events
Tc - check frequently during execution
Ts - print statistics
Tv - verify result: structure, convexity, and redundancy
Tz - send all output to stdout
TFn - report summary when n or more facets created
TI file - input data from file, no spaces or single quotes
TO file - output results to file, may be enclosed in single quotes
TPn - turn on tracing when halfspace n added to intersection
TMn - turn on tracing at merge n
TWn - trace merge facets when width > n
TVn - stop qhull after adding halfspace n, -n for before (see TCn)
TCn - stop qhull after building cone for halfspace n (see TVn)
Precision options:
Cn - radius of centrum (roundoff added). Merge facets if non-convex
An - cosine of maximum angle. Merge facets if cosine > n or non-convex
C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge
Rn - randomly perturb computations by a factor of [1-n,1+n]
Un - max distance below plane for a new, coplanar halfspace
Wn - min facet width for outside halfspace (before roundoff)
Output formats (may be combined; if none, produces a summary to stdout):
f - facet dump
G - Geomview output (dual convex hull)
i - non-redundant halfspaces incident to each intersection
m - Mathematica output (dual convex hull)
o - OFF format (dual convex hull: dimension, points, and facets)
p - vertex coordinates of dual convex hull (coplanars if 'Qc' or 'Qi')
s - summary (stderr)
More formats:
Fc - count plus redundant halfspaces for each intersection
- Qc (default) for coplanar and Qi for other redundant
Fd - use cdd format for input (homogeneous with offset first)
FF - facet dump without ridges
FI - ID of each intersection
Fm - merge count for each intersection (511 max)
FM - Maple output (dual convex hull)
Fn - count plus neighboring intersections for each intersection
FN - count plus intersections for each non-redundant halfspace
FO - options and precision constants
Fp - dim, count, and intersection coordinates
FP - nearest halfspace and distance for each redundant halfspace
FQ - command used for qhalf
Fs - summary: #int (8), dim, #halfspaces, #non-redundant, #intersections
for output: #non-redundant, #intersections, #coplanar
halfspaces, #non-simplicial intersections
#real (2), max outer plane, min vertex
Fv - count plus non-redundant halfspaces for each intersection
Fx - non-redundant halfspaces
Geomview output (2-d, 3-d and 4-d; dual convex hull)
Ga - all points (i.e., transformed halfspaces) as dots
Gp - coplanar points and vertices as radii
Gv - vertices (i.e., non-redundant halfspaces) as spheres
Gi - inner planes (i.e., halfspace intersections) only
Gn - no planes
Go - outer planes only
Gc - centrums
Gh - hyperplane intersections
Gr - ridges
GDn - drop dimension n in 3-d and 4-d output
Print options:
PAn - keep n largest facets (i.e., intersections) by area
Pdk:n- drop facet if normal[k] <= n (default 0.0)
PDk:n- drop facet if normal[k] >= n
Pg - print good facets (needs 'QGn' or 'QVn')
PFn - keep facets whose area is at least n
PG - print neighbors of good facets
PMn - keep n facets with most merges
Po - force output. If error, output neighborhood of facet
Pp - do not report precision problems
. - list of all options
- - one line descriptions of all options
Up: Home page for Qhull
Up: Qhull manual: Table of Contents
To: Programs
Options
Output
Formats
Geomview
Print
Qhull
Precision
Trace
To: synopsis
input outputs
controls graphics
notes conventions
options
The Geometry Center
Home Page
Comments to: qhull@qhull.org
Created: Sept. 25, 1995 --- Last modified: see top
diff --git a/index.htm b/index.htm
index 2053789..16fd51d 100644
--- a/index.htm
+++ b/index.htm
@@ -1,279 +1,280 @@
Qhull code for Convex Hull, Delaunay Triangulation, Voronoi Diagram, and Halfspace Intersection about a Point
URL: http://www.qhull.org
To:
News
Download
CiteSeer
Images
Manual
FAQ
Programs
Options
Qhull
|
Qhull computes the convex hull, Delaunay triangulation, Voronoi diagram,
halfspace intersection about a point, furthest-site Delaunay
triangulation, and furthest-site Voronoi diagram. The source code runs in
2-d, 3-d, 4-d, and higher dimensions. Qhull implements the Quickhull
algorithm for computing the convex hull. It handles roundoff
errors from floating point arithmetic. It computes volumes,
surface areas, and approximations to the convex hull.
Qhull does not support triangulation of non-convex surfaces, mesh
generation of non-convex objects, medium-sized inputs in 9-D
and higher, alpha shapes, weighted Voronoi diagrams, Voronoi volumes, or
constrained Delaunay triangulations,
Qhull 2012.1 fixes qhull-go for Windows 64-bit. If you use Qhull 2003.1. please upgrade to 2012.1 or apply poly.c-qh_gethash.patch.
|
Introduction
Qhull Documentation and Support
Related URLs
FAQs and Newsgroups
The program includes options for input transformations,
randomization, tracing, multiple output formats, and execution
statistics. The program can be called from within your
application.
You can view the results in 2-d, 3-d and 4-d with Geomview. An alternative
is VTK.
For an article about Qhull, download from
ACM or CiteSeer:
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
Abstract:
The convex hull of a set of points is the smallest convex
set that contains the points. This article presents a
practical convex hull algorithm that combines the
two-dimensional Quickhull Algorithm with the general
dimension Beneath-Beyond Algorithm. It is similar to the
randomized, incremental algorithms for convex hull and
Delaunay triangulation. We provide empirical evidence that
the algorithm runs faster when the input contains non-extreme
points, and that it uses less memory.
Computational geometry algorithms have traditionally
assumed that input sets are well behaved. When an algorithm
is implemented with floating point arithmetic, this
assumption can lead to serious errors. We briefly describe a
solution to this problem when computing the convex hull in
two, three, or four dimensions. The output is a set of
"thick" facets that contain all possible exact convex hulls
of the input. A variation is effective in five or more
dimensions.
Up: Past Software
Projects of the Geometry Center
URL: http://www.qhull.org
To:
News
Download
CiteSeer
Images
Manual
FAQ
Programs
Options
The Geometry Center Home Page
Comments to: qhull@qhull.org
Created: May 17 1995 ---
diff --git a/src/Changes.txt b/src/Changes.txt
index efa9e9c..52f9a1f 100644
--- a/src/Changes.txt
+++ b/src/Changes.txt
@@ -1,1674 +1,1912 @@
.............This file lists all changes to qhull and rbox.....................
------------
Need help
- Qhull needs RPM and Debian builds (CMake's CPackRMP and CPackDeb).
- Add an Autotools build for everything
- Set up debian build [octave-maintainers]
Please keep debian files in config/
- Qhull needs a mirror/archive site for old and new builds
+ - Constrained delaunay triangulation via Shewchuk's algorithm (ACM Symp. Comp. Geo., 1998)
- The C++ interface needs work. Give it a try and make it better.
http://gitorious.org/qhull/
- Document with Qt conventions using Doxygen (//! and //!<)
- Produce conformant triangulations for merged facets using option 'Qt'
To do
+ - Can allocate memory for QhullSet using Qhull.qhmem, Then default constructors for QhullVertexSet etc.
- Review email for doc changes before jun'10
- Git: Create signed tags for Qhull versions
- Wiki: Add FIXUP to QH11026 for known problems
+ - Review all FIXUP
+ - Update README for libqhullr etc.
- Notes to compgeom on conformant triangulation and Voronoi volume
- Set File Ver and Product Ver in dll
- - For the C++ interface, make qh_qh a parameter instead of a global static
- This replaces qh_QHpointer. It simplifies multithreading.
- Compute the convex hull of each Voronoi or Delaunay region
- Performance test of qset and qhull
-
+ - Rescale output to match 'QbB' on input [J. Metz, 1/30/2014 12:21p]
- qh-get.htm: List the Window OSs for Qhull [T. Winkler]
+ - Add publications that compare Qhull and CGAL. Review results
- Reconsider Qhull version numbering (e.g., Traveler 4/5/12)
+ - Add interior point for automatic translation?
+ - Allow comma separated input?
+ - Allocate a new QhullPoint
+ - countT -1 used as a flag in Coordinates.mid(), QhullFacet->id()
+ Also QhullPoints indexOf and lastIndexOf
+ Also QhullPointSet indexOf and lastIndexOf
+ - Coordinates.indexOf assumes countT is signed (from end)
+ - Coordinates.lastIndexOf assumes countT is signed (from end)
+ - All error messages with countT are wrong, convert to int?
+ - Review all cpp code for 'int'
+ - Review all c code for 'int'
+ - RboxPoints.qh_fprintf_rbox, etc. message 9393 assumes countT but may be int, va_arg(args, countT); Need to split
+ - vertexT unsigned id:24; /* too small */
+ - Why QhullFacetList.PrintFacetList and .PrintFacet?
+ - Remove s_qhull_output
+ - qset_r.h defines countT -- duplicates code in user_h.h -- need to add to qset.h/user.h
+ - rbox_errexit assumed to exit. Protect with a flag?
+ - checkAndFreeQhullMemory does not work since it does not free qhmem itself.
+ - Check base address for qhstatT, add Qhull initializers
+ - Review all classes
+ Check that assignment copies everything
+ Check alignment for Fields
+ Qhull& constructors before QhullQh* constructors, otherwise the same
+ operator= for all
+ check explicit
+ Remove print(), add << T if needed
+ Remove QhullFacet.print() -- Use << instead
+ - Reduce includes
+ - Document C++
+ Designed for exploring the results of Qhull.
+ All objects contain a QhullQh reference, making them memory inefficient.
+ May also use libqhull (e.g., FOREACHfacet_(...))
+ - Review default constructors (QhullPoint OK)
+ - QhullVertexSet uses QhullSetBase::referenceSetT() to free it's memory. Probably needed elsewhere
+ - Add defineAs to each object
+ - Add QList and vector instance of facetT*, etc.
+ - Generalize QhullPointSetIterator
+ - Review all tests
+ Add QhullStat_test
+ Add printIdentifiers to Set tests
+ Add QhullVertexSet_test
+ Add Qhull* to constructors
+ Test QhullQh* constructors
+ Test QhullFacetList.operator=
+ Test QhullLinkedList.operator=
+ Test QhullFacetSet.operator=
+ Test QhullFacetSet.print("message")
+ Test QhullPoints.operator=
+ Test QhullPointSet.operator=
+ Test QhullSet.operator=
+ Test qh_NOmem, etc.
+ - Reviewed
+ QhullPoint_test
+ - Update LASTerror for qhullpcpp.QhullError.h
+ - Check that QtCreator can load and build with CMakefile
+ - Incremental addition of input points to existing tesselation
+ - Add reference (compares to cgal, http://www.mcs.anl.gov/papers/P5154-0614.pdf, 4x more memory, cgal much faster)
+ Y. Liu and J. Snoeyink, “A Comparison of Five Implementations of 3D Delaunay Tessellation,” Combinatorial and Computational Geometry, vol. 52, pp. 439–458, 2005.
+ - Fix no-more facets error
+ - Fix interface to Qhull. Shouldn't do all the work in the constructor
+ void runQhull(const char *qhullCommand2);
+------------
+Dec'14 notes
+
+make-vcproj.sh -- Renames build/ to build-prev. Creates build, build-vc and build-qt (needs editing)
+Renamed build to build-new
+Copied build-prev to build and renamed as build-mar14
+Devenv loaded build/qhullr.sln with qhullmini
+ build/qhulltest-mini/qhullmini.vcproj
+ build/libqhullcpp/libqhullcpp.vcproj
+ build/libqhullstaticr/libqhullstaticr.vcproj
+Includes
+ build/libqhullr/libqhullr.vcproj
+
+Load Qt Creator (Oct'14) with src/qhull-all.pro -- The project is odd due to the include files
+Successfully compiled and ran qhullmini with QhullPoint_test
+Updated Perforce
+Added user_eg3
+
------------
Qhull
+ - Fixed documentation for 'include' path in qh-code.htm. It should be include/libqhull [fe rew]
+ - Fixed documentation for 'i' in qconvex.htm. It triangulates in 4-d and higher [
+ - Clarified qhalf space documentation for the interior point [J. Santos]
- Rename debugging routines dfacet/dvertex to qh_dfacet/qh_dvertex
- Rename rbox routines to qh_roundi/qh_out1/qh_out2n/qh_out3n
- Rename dfacet and dvertex to qh_dfacet and qh_dvertex
- Rename user_eg, user_eg2, and user_eg3 to user_eg7,etc.
- Rewrote user_eg, user_eg2, and user_eg3 as reentrant code
- Replace 'qhmem .zzz' with 'qhmem.zzz'
- Removed spaces between function and parentheses
- Rename 'enum statistics' to 'enum qh_statistics'
- Rename 'qh_rand_seed' to 'qh_last_random'. Declare it as DATA
- Declare rbox as DATA in qhull-exports.def and qhull_p-exports.def
- In comments, use 'qh.zzz' to reference qhT fields
- In qh_fprintf, use qhmem.ferr to report errors
- qh_fprintf may be called for errors in qh_initstatistics and qh_meminit
- After qh_meminit, qhmem.ferr is non-zero
- Update qh_MEMalign in testqset.c to user.h (with realT and void*)
-
-qhullr
+ - Split rboxT into a header file
+ - Add rboxlib.h to libqhull_a.h
+ - Rename PI to qh_PI and extend to 30 digits
+ - Rename MAXdim to qh_MAXdim
+ - Change spacing for type annotations '*' and '&' in C++ header files
+ - Remove 'inline' annotation from explicit inline declarations
+ - Column 25 formatting for iterators, etc.
+ - Use '#//!\name' for section headers
+ - QhullFacet.cpp: zinc_(Zdistio);
+ - Set qhT.NOerrexit on initialization
+ - Clear qhT.ALLOWrestart in qh_errexit
+ - Replace longjmp with qh_errexit_rbox in qh_rboxpoints
+ - Add jmpExtra after rbox_errexit to protect against compiler errors
+
+qhullr (reentrant Qhull)
+ - Make the Qhull data structure (qh_qh) a parameter instead of a global static
+ It simplifies multithreading and the C++ user interface
+ All functions are reentrant (Qt: "A reentrant function can ... be called simultaneously from multiple threads, but only if each invocation uses its own data.")
+ This replaces qh_QHpointer.
+ New libraries
+ libqhullr -- Shared library with reentrant sources (e.g., poly_r.h and poly_r.c which replace libqhull's poly.h and poly.c)
+ libqhullstaticr -- Static library with the same sources as libqhullr
+ libqhullcpp -- The C++ interface using libqhullr (further notes below)
+ New executables
+ qhulltest -- Test the C++ interface using Qt
+ testqsetr -- Test qset_r.c (the reentrant version of qset.c
+ Renamed libraries and executables
+ libqhullpcpp -- The old C++ interface using qh_QHpointer and libqhullp (previously called libqhullcpp)
+ qhullptest -- The old test program for the C++ interface (previously called qhulltest)
+
+ Source code changes for libqhullr
- Remove qh_save_qhull(), qh_restore_qhull(), and qh.old_qhstat from global_r.c
- Remove qh_freeqhull2() (global_r.c)
- Remove qh_freestatistics() (stat_r.c)
- Remove qh_compare_vertexpoint (qhT is not available, unused code)
- Remove conditional code for __POWERPC__ from unix_r.c and rbox_r.c
- Move qh_last_random into qh->last_random (random_r.c)
- - Rename sources files with a '_r' suffix
+ - Rename sources files with a '_r' suffix. qhull_a.h becomes qhull_ra.h
- Replace 'qh' macro with 'qh->'
- Replace global qhT with parameter-0
- Add qhmemT to beginning of qhT. It may not be used standalone.
- Add qhstatT to end of qhT
- Remove qhull_inuse
- Change qhmem.zzz to qh->qhmem.zzz
- Replace qh_qhstat with qh->qhstat
- Remove qh_freestatistics
- Replace qh_last_random with qh->last_random
- Replace rboxT with qh->rbox_errexit, rbox_isinteger, rbox_out_offset
- Replace rbox.ferr/fout with qh->ferr/fout
- No qh for qh_exit, qh_free, qh_malloc, qh_strtod, qh_strtol, qh_stddev
- New qmake include files qhull-app-c_r.pri, qhull-app-shared_r.pri, qhull-libqhull-src_r.pri
+ - Replace 'int' with 'countT' and 'COUNTmax' for large counts and identifiers
+ - qhset converted to countT
+ - Removed vertexT.dim -- No longer needed by cpp
+ Removed MAX_vdim
+ - Guarantee that qh->run_id!=0. Old code assumed that qh_RANDOMint was 31 bits
C++ interface
- Reimplement C++ interface on reentrant libqhullr instead of libqhull
- Renamed libqhullcpp to libqhullpcpp
- Renamed qhulltest to qhullptest
- Renamed qhull-app-cpp.pri to qhull-app-cpp_p.pri
+ - Added QhullVertexSet.h to libqhullcpp.pro and libqhullpcpp.pro
+ - Replaced UsingLibQhull with QhullQh and macro QH_TRY
+ Removed UsingLibQhull.currentAngleEpsilon and related routines
+ Replaced globalDistanceEpsilon with QhullQh.distanceEpsilon
+ Replaced globalAngleEpsilon with QhullQh.angleEpsilon
+ Replaced FACTORepsilon=10 with QhullQh.factor_epsilon=1.0
+ - Fixed double free by QhullVertexSet's copy constructor if qhsettemp_defined
+ - Moved messaging from Qhull to QhullQh
+ - RboxPoints(rboxCommand).comment() includes the command with its
+ - Add check of RboxPoints* in qh_fprintf_rbox
+ - Renamed Qhull.initializeQhull to Qhull.allocateQhullQh
+ - Renamed UsingQhullLib.checkQhullMemoryEmpty to QhullQh.checkAndFreeQhullMemory
+ Added qh_freeqhull(!qh_ALL) as done by unix.c and other programs
+ - Moved QhullPoints.extraCoordinatesCount into QhullPoints.cpp
+ - Changed QhullPoint.operator== to sqrt(distanceEpsilon)
+ - Replaced section tags with '#//!\name ...'
+ - PointCoordinates.operator=: initialize QhullPoints, otherwise does not copy point_dimension
+
+C++ interface for most classes
+ - Remove qhRunId
+ - Add QhullQh *qh_qh to all types
+ Pointer comparisons of facetT,etc. do not test corresponding qh_qh
+ Added to end of type for debugging information, unless wasteful alignment
+ - Add QhullQh * to all constructors
+ - All constructors may use Qhull & instead of QhullQh *
+ - For inherited QhullQh types, change to 'protected'
+ - Renamed 'o' to 'other' except where used extensively in iterators
+ - Except for conditional code, merged the Conversion section into GetSet
+ - Removed empty(). Use isEmpty() instead
+ - Add operator= instead of keeping it private
+ - print_message=0 not allowed. Use "" instead.
+C++ interface by class
+ - Coordinates
+ Removed empty(). Use isEmpty() instead
+ Reformated the iterators
+ Convert to countT
+ - PointCoordinates
+ Constructor requires Qhull or QhullQh* pointer
+ Renamed point_comment to describe_points
+ Convert to countT
+ - Qhull
+ Remove qhull_run_i
+ Remove qh_active
+ Replaced qhull_dimension with qh->input_dim //! Dimension of result (qh.hull_dim or one less for Delaunay/Voronoi)
+ Remove globals s_qhull_output= 0;
+ Renamed qhullQh() to qh()
+ Added check of base address to allocateQhullQh(), Was not needed for qhullpcpp
+ - QhullFacet
+ Constructor requires Qhull or QhullQh* pointer
+ Convert to countT
+ Dropped implicit conversion from facetT
+ Dropped runId
+ - QhullFacetList
+ Constructor requires Qhull or QhullQh* pointer
+ Convert to countT
+ Dropped runId
+ - QhullFacetSet
+ Removed empty(). Use isEmpty() instead
+ Constructor requires Qhull or QhullQh* pointer
+ Convert to countT
+ Dropped runId
+ Add operator=
+ Implement print("message")
+ - QhullHyperplane
+ Constructor requires Qhull or QhullQh* pointer
+ Reorganized
+ - QhullLinkedList
+ Add operator=
+ Removed empty(). Use isEmpty() instead
+ Convert to countT
+ - QhullPoint
+ Constructor requires Qhull or QhullQh* pointer
+ An empty QhullPoint sets point_dimension to hull_dim
+ Added checks for point_coordinates==0, i.e., QhullPoint(q)
+ Removed QhullPoint::id, use QhullPoint.id() instead
+ distance() throws an error if dimension doesn't agree or if a point is undefined
+ Convert to countT
+ Removed test of qh_qh from operator==
+ Use cout<
[R. Richter, S. Pasko]
- Remove deprecated libqhull/qhull.h
Use libqhull/libqhull.h instead. Avoids confusion with libqhullcpp/Qhull.h
- Makefile: Add LIBDIR, INCDIR, and DESTDIR to install [L.H. de Mello]
Separate MAN install from DOC install
Create install directories
Installs headers to include/libqhull, include/libqhullcpp, include/road
- CMakeLists.txt: Add MAN_INSTALL_DIR for qhull.1 and rbox.1 man pages
Add RoadTest.h to include/road for Qt users (road_HEADERS)
- Renamed md5sum files to avoid two extensions
- qh-get.htm: Add Readme links and 2009.1 note.
- qh-optf.htm: Fix link
- index.htm: Updated Google Scholar link
- qhull-zip.sh: Improved error message.
------------
Qhull 2011.1 2011/04/17 6.2.0.1373
Changes to deliverables
- qvoronoi: Deprecated 'Qt' and 'QJn'. Removed from documentation and prompts.
These options produced duplicate Voronoi vertices for cospherical data.
- Removed doskey from Qhull-go.bat. It is incompatible with Windows 7
- Added 'facets' argument to user_eg3.cpp
- user_eg links with shared library
- qhulltest.cpp: Add closing prompt.
Changes to build system
- Reorganized source directories
- Moved executables to bin directory
- Add CMake build for all targets (CMakeFiles.txt) [M. Moll assisted]
- Add gcc build for all targets (Makefile)
- Fixed location of qhull.man and rbox.man [M. Moll]
- Add DevStudio builds for all targets (build/*.vcproj)
- Added shared library (lib/qhull6.dll)
Added qh_QHpointer_dllimport to work around problems with MSVC
- Added static libraries with and without qh_QHpointer (lib/qhullstatic.lib)
- Added eg/make-vcproj.sh to create vcproj/sln files from cmake and qmake
- Document location of qh_QHpointer
- Use shadow build directory
- Made -fno-strict-aliasing conditional on gcc version
- Added src/qhull-app-cpp.pri, src/qhull-app-c.pri, etc. for common settings
- Add .gitignore with ignored files and directories.
- Use .git/info/exclude for locally excluded files.
- Fixed MBorland for new directory structure
Changes to documentation
- qvoronoi.htm: Remove quotes from qvoronoi example
- qhull-cpp.xml: Add naming conventions
- index.htm: Add Google Scholar references
- qh-optf.htm: Add note about order of 'Fn' matching 'Fv' order [Q. Pan]
- Add patch for old builds in qh-get.htm
- Added C++ compiling instructions to README.txt
- Add instructions for fixing the DOS window
- Changed DOS window to command window
- Fixed html links
- qh-get.htm: Dropped the Spanish mirror site. It was disabled.
Changes to C code
- mem.h: Define ptr_intT as 'long long' for Microsoft Windows _win64 builds.
On Linux and Mac, 'long' is 64-bits on a 64-bit host
- Added qh_QHpointer_dllimport to work around MSVC problem
- qconvex.c,etc.: Define prototype for _isatty
- Define MSG_QHULL_ERROR in user.h
- Move MSG_FIXUP to 11000 and updated FIXUP QH11...
Changes to test code
- Add note to q_test than R1e-3 may error (qh-code.htm, Enhancements)
- Add test for executables to q_eg, etc.
- Fixed Qhull-go.bat. QHULL-GO invokes it with command.com,
Changes to C++ interface
- QhullFacet: Added isSimplicial, isTopOrient, isTriCoplanar, isUpperDelaunay
- Added Qhull::defineVertexFacetNeighbors() for facetNeighbors of vertices.
Automatically called for facet merging and Voronoi diagrams
Do not print QhullVertex::facetNeighbors is !facetNeighborsDefined()
- Add Fixup identifiers
- QhullError: Add copy constructor, assignment operator, and destructor
- Add throw() specifiers to RoadError and QhullError
- Renamed RoadError::defined() to RoadError::isDefined()
- Add #error to Qhull.h if qh_QHpointer is not defined
Changes to C++ code
- Fixed bug reported by renangms. Vertex output throws error QH10034
and defineVertexNeighbors() does not exist.
- Define QHULL_USES_QT for qt-qhull.cpp [renangms]
- Reviewed all copy constructors and copy assignments. Updated comments.
Defined Qhull copy constructor and copy assignment [G. Rivet-Sabourin]
Disabled UsingQhullLib default constructor, copy construct, and copy assign
- Merged changes from J. Obermayr in gitorious/jobermayrs-qhull:next
- Fix strncat limit in rboxlib.c and global.c
- Changes to CMakeLists.txt for openSUSE
- Fixed additional uses of strncat
- Fixed QhullFacet::PrintRidges to check hasNextRidge3d()
- Removed gcc warnings for shadowing from code (src/qhull-warn.pri)
- Removed semicolon after extern "C" {...}
- Removed experimental QhullEvent/QhullLog
- Use fabs() instead of abs() to avoid accidental conversions to int
- Fixed type of vertex->neighbors in qh_printvoronoi [no effect on results]
- Removed unnecessary if statement in qh_printvoronoi
------------
qhull 2010.1 2010/01/14
- Fixed quote for #include in qhull.h [U.Hergenhahn, K.Roland]
- Add qt-qhull.cpp with Qt conditional code
- Add libqhullp.proj
- Add libqhull5 to Readme, Announce, download
- Reviewed #pragma
- Reviewed FIXUP and assigned QH tags
- All projects compile with warnings enabled
- Replaced 'up' glyphs with »
- Moved cpp questions to qh-code.htm#questions-cpp
- Moved suggestions to qh-code.htm#enhance
- Moved documentation requests to qh-code.htm#enhance
- Add md5sum file to distributions
- Switched to DevStudio builds to avoid dependent libraries, 10% slower
Removed user_eg3.exe and qhullcpp.dll from Windows build
Fix qhull.sln and project files for qh_QHpointer
- Add eg/qhull-zip.sh to build qhull distribution files
------------
qhull 2010.1 2010/01/10
- Test for NULL fp in qh_eachvoronoi [D. Szczerba]
qhull 2010.1 2010/01/09
Changes to build and distribution
- Use qh_QHpointer=0 for libqhull.a, qhull, rbox, etc.
Use -Dqh_QHpointer for libqhullp.a, qhullcpp.dll, etc.
qh_QHpointer [2010, gcc] 4% time 4% space, [2003, msvc] 8% time 2% space
- Add config/ and project/debian/ for Autoconf build [R. Laboissiere]
from debian branch in git and http://savannah.nongnu.org/cvs/?group=qhull
- Add CMakeLists.txt [kwilliams]
- Fix tabs in Makefile.txt [mschamschula]
- Add -fno-strict-aliasing to Makefile for gcc 4.1, 4.2, and 4.3 qset segfault
- Remove user_eg.exe and user_eg2.exe from Windows distribution
- Order object files by frequency of execution for better locality.
Changes to source
- Remove ptr_intT from qh_matchvertices. It was int since the beginning.
- user.h requires for CLOCKS_PER_SEC
- Move ostream<centrum for triangulated facets
- Fixed mindist initialization if !testcentrum in io.c findbest_test [Ratcliff]
- Fixed parentheses around warning for missing 'Qc' [qh_initqhull_outputflags]
- Fixed rbox buffer overflow of 'command' when appending seedbuf
- Fixed option string for 'rbox t t999'. Although seed was correctly set to 999,
a random seed was appended to the rbox comment (e.g., 'rbox t t999 t32343')
- Fixed upper bound of sanity check for qh_RANDOMmax in qh_initqhull_globals()
Changes to C code
- Reordered #include from specific to general. Move up .h for module.
- Removed qh.old_stat -- never used
- Removed qh_clearcenters from qh_freeqhull. Duplicated by qh_delfacet
- qh_printcenter [io.c] removed unreachable fprintf argument
- qh_getarea() [geom2.c] ignored on multiple calls (qh.hasAreaVolume)
- qh_getarea() [geom2.c] checks facet->isarea. Set by QhullFacet.facetArea()
- qh_triangulate() [poly2.c] ignored on multiple calls (qh.hasTriangulation)
- Add statistics for vertex_visit and visit_id to buildtracing
- Defined scale and offset parameters for qh_randomfactor
Bug fixes and changes to mem.c/mem.h
- Fixed qhmem.totshort (total short memory in use)
- Memory tracing (T5) redone for sort order by object
- Added full tracing for short memory allocations.
- Added qhmem.totfree (total short memory on freelists)
Increases size of qh_memalloc_ and qh_memfree_
- Added qhmem.totdropped (leftover freesize at end of each short buffer)
- Added qhmem.totunused (short size - request size)
- Added qhmem.totbuffer (total short memory buffer w/o links)
- Added memory statistics to qh_NOmem;
- Added qh_memtotal to track allocated memory
- Renamed qh_memfree parameter to 'insize' for consistency with qh_memalloc
- Removed qhmem.curlong. qa_memfreeshort computes curlong from cntlong and cntfree
- In mem.h, changed ptr_intT to long. qh_meminit() checks that it holds a 'void*'
Fixed g++ and devstudio warnings
- Except for bit field conversions, compiles cleanly with
-Wall -Wextra -Wshadow -Wcast-qual -Wwrite-strings -Wno-sign-conversion -Wconversion
- Fixed warnings at VC8, level 4
- Fix data types to remove conversion warnings [kwilliams]
- Use size_t for calls to malloc,etc [kwilliams]
Retained int sizes for qset.h and mem.h. Follows Qt convention
and is easier to work with. int can be 64-bits if 2 billion facets
- Change literal strings to const char* [kwilliams]
- Added type casts to SETfirst and SETsecond [amorilia+alphax]
- getid_() returns an int [kwilliams]
- Add missing const annotations [kwilliams]
- Fixed 64-bit warnings (marked with "WARN64")
- Convert sizeof to (int) for int parameters
- In libqhull.c, added explicit casts from long to float, Avoids warning
- In global.c, cast time() to int for QRandom-seed. Avoids warning
Changes to C code for C++ support
- Add sln, vcproj, and qtpro files for building Qhull -- add to README notes
- Added dim to vertexT for cpp interface. Reduced size of qh.vertex_visit
- qh_produce_output [io.c] may be called multiple times (C++ interface)
- Moved SETsizeaddr_() to qset.h for use by QhullSet.cpp
- Option 'Tz' sets flag qh.USEstdout for QhullPoints.cpp
- Added support for multiple output runs from QhullPoints.outputQhull
- qh_clear_outputflags() resets the output flags
- qh_initqhull_outputflags split from qh_initqhull_globals
- Added qh.run_id, a random identifier for this instance of Qhull (QhullPoints)
- For qh.run_id, initqhull_start initializes qh_RANDOMseed to time instead of 1
- Extracted qh_argv_to_command (random.c) from qh_init_qhull_command and fixed a buffer overflow
- Moved qh_strtod/qh_strtol from global.c to random.c for use in rboxlib.c
- Split out random functions into random.c
- Added message codes to qh_fprintf(). See its definition in user.c
- Replaced exit, malloc, free, fprintf, and fputs with qh_malloc,...[J.W. Ratcliff]
- Added qh_fprintf, qh_malloc, qh_free, ph_printhelp_narrowhull to user.c
- Moved qh_printhelp_degenerate and qh_printhelp_singular from io.c to user.c
- Clear qh.ERREXITcalled at end of qh_errexit().
Documentation:
- Fixed out-of-date CiteSeer references
- Renamed html/qh-in.htm to html/qh-code.htm
- Add reference to 'Qt' to 'i'
- Add reference to 'FS' to 'FA'
- qh-impre.htm discusses precision issues for halfspace intersection
- Add cross references between options 'FA' and 'FS'
- Added link to Wolfram Research's MathWorld site
- Updated Fukuda's links
- Changed copyright to C.B. Barber for C++, documentation, and merge.c
- Updated Qhull citation with page numbers.
- Proposed project: constructing Voronoi diagram
- Proposed project: computing Voronoi volumes
- Replaced tabs with spaces in qhull.txt and rbox.txt
------------
qhull 2009.1 2009/6/11
This is a maintenance release done by Rafael Laboissiere .
- src/rbox.c (main): Avoid problems of evaluation order when
pre-incrementing arguments of strtod
- src/io.c (qh_produce_output), src/stat.c (qh_initstatistics): Use %lu
instead of %d in the format string for arguments of type size_t
- html/qhull.man, html/rbox.man: Fix several syntax, macros, and hyphen
problems in man pages
- The Autotools files have been generated with modern version of autoconf (2.63),
automake/aclocal (1.10.2), and libtool (2.2.6)
- Some character issues in the man pages are fixed
------------
qhull 2003.1 2003/12/30
New Features:
- Add Maple output ('FM') for 2-d and 3-d convex hulls [T. Abraham]
Breaking Code Changes:
- Annotate C code with 'const'. An ANSI compatible compiler is required.
Bug Fixes and Code Changes:
- Fixed qh_findbest() for upperdelaunay facets w/o better, lower neighbors
For library users and some qhull users [A. Cutti, E. Milloti, K. Sun]
- Preserved qhmem.ferr in qh_memfreeshort() for library users
- Removed 'static' from qh_compare... for io.h and merge.h [V. Brumberg]
- Split out qh_initqhull_start2() to avoid allocating qh_qh
- Split out qh_freeqhull2() to avoid freeing qh_qh
- Split out qh_produce_output2() and qh_prepare_output()
- qh_initstatistics() frees a previously existing qh_qhstat
- qh_initqhull_start2() checks that qh_initstatistics() called first
Documentation:
- Add warning to findDelaunay() and qh_in.htm about tricoplanar facets
- Noted Edelsbrunner's Geometry & Topology for Mesh Generation [qh-impre.htm]
- Noted Gartner's Miniball algorithm [qh_impre.htm]
- Noted Veron and Leon's shape preserving simplification [qh_impre.htm]
qhull 2003.1 2003/12/19
Bug Fixes:
- Reversed coordinate order for qh.ATinfinity in qh_projectinput [V. Brumberg]
This effects:
Qhull library 'd' or 'v' users with 'Qz' and unequal coordinate ranges.
qdelaunay/qvoronoi users with 'Qbk:0Bk:0', 'Qz', and unequal coordinate ranges
Changes to code:
- Replaced qh_VERSION with qh_version in global.c [B. Pearlmutter]
The previous techniques were either clumsy or caused compiler errors
- Removed unused variables from qh_findbest and qh_findbestnew [B. Pearlmutter]
- Note that qh.TESTpoints was added in 2002.1 for tsearch implementation
Changes to distribution:
- Added Unix distribution including Debian files [R. Laboissiere]
The previous Unix distribution is now the source distribution
- Added rpm distribution [L. Mazet]
- Investigated generation of Win32 dll. Need to define a C++ interface.
Changes to documentation:
- Moved Qhull to www.qhull.org (geom.umn.edu is not available)
- The Geometry Center is archived at http://www.geom.uiuc.edu
- Reviewed introduction to each program
Triangulated output ('Qt') is more accurate than joggled input ('QJ')
qdelaunay is 'qhull d Qbb' [C. Ulbrich]
qvoronoi is 'qhull v Qbb'
Added example of non-simplicial intersection to halfspace intersections
- Added warning about using the Qhull library.
- Added qhull timings to When to use Qhull [C. Ulbrich]
- Reorganized the home page index and the manual index
- Moved qh-home.htm to index.htm
Changes to examples
- Fixed options for eg/eg.t23.voronoi.imprecise [B. Pearlmutter]
------------
qhull 2002.1 2002/8/20
Changes to distribution:
- Set up savannah.nongnu.org/projects/qhull/ [R. Laboissiere]
- Set up www.thesa.com as a backup
- Added qh-get.htm, a local copy of the download page
- Added Visual C++ interface to Qhull, qhull_interface.cpp [K. Erleben]
- Use HTTP instead of FTP for downloading Qhull
- Renamed qhull-1.0.sit.hqx
Bug fixes:
- Fixed sign of coefficients for cdd halfspaces ('FD','Fd') [T. Abraham]
Changes to code:
- Replace qh_version with qh_VERSION in libqhull.h.
Allows shared libraries and single point of definition
- Added qh.TESTpoints for future implementation of tsearch
Changes to build
- Makefile.txt works under cygwin
- Added Make-config.sh to create a Debian build [R. Laboissiere]
- Added .exe to Makefile.txt#clean.
- In README, use -fno-strict-aliasing with gcc-2.95.1 [Karas, Krishnaswami]
- Fixed chmod in Makefile.txt [B. Karas]
Documentation updates
- Documented input options for each program [A. Montesinos]
- FAQ: "How to get the radii of the empty spheres for Voronoi vertices"
URL updates:
- Changed official URL from locate/qhull to software/qhull
- Changed URLs from relative to absolute in qh-home.htm and qh-get.htm
- Added URL for Newsgroup: comp.soft-sys.matlab
- Added URL for GNU Octave
- Added URLs for Google and Google Groups
- Replaced qhull_mail.html and qhull_bug.html with mailto links.
- Removed URL for Computational Geometry Tribune
- Changed URL for locate/cglist to software/cglist
- Used site relative links for qh-home.htm
------------
qhull 3.1 2001/10/04
New features
- Added option 'Qt' to triangulate non-simplicial facets
- Added option 'TI file' to input data from file
- Added option 'Q10' to prevent special processing for narrow distributions
e.g., RBOX 1000 L100000 s G1e-6 t1001803691 | QHULL Tv Q10
- Tried to compute Voronoi volumes ('Pv'). Requires dual face graph--not easy
See Clarkson's hull program for code.
Changes to options
- Added numtricoplanars to 'Fs'. Number of good, triangulated facets for 'Qt'
- Added Zdelvertextot to 'Fs'. If non-zero and Delaunay, input is degenerate
- Qhull command ('FQ') may be repeated.
- If 'TPn' and 'TWn' defined, trace the addition of point 'n'
otherwise continue tracing (previously it stopped in 4-d)
- Removed 'Ft' from qdelaunay. Use 'Qt o' or 'qhull d QJ Qt' instead.
For non-simplicial regions, 'Ft' does not satisify the Delaunay property.
- If 'Po' or 'TVn', qhull checks outer planes. Use 'Q5' to turn off.
- If 'T4', print facet lists and check polygon after adding each point
Corrections to code
- rbox: allow 'c' and 'd' with 's r', meshes, etc.
- qh_findbest: redesigned as directed search. qh_findbesthorizon for coplanar
qh_findbest is faster for many distributions
- qh_findbestnew: redesigned to search horizon of coplanar best newfacets
needed for distributions with a sharp edge,
e.g., rbox 1000 s Z1 G1e-13 | qhull Tv
- qh_findbest/qh_findbestnew: search neighbors of better horizon facets
was needed for RBOX 1000 s Z1 G1e-13 t996564279 | qhull Tv
and RBOX 1000 s W1e-13 P0 t996547055 | QHULL d Qbb Qc Tv
- qh_findbest with noupper: could return an upperdelaunay facet if dist>qh.MINoutside.
- qh_findbestnew: allow facet->upperdelaunay if dist > qh.MINoutside
- qh_partitioncoplanar: call qh_partitionpoint if outside and perpendicular
for distributions with a sharp edge
- qh_partitionvisible: report precision error if all newfacets degenerate.
was needed for RBOX 1000 s W1e-13 t995138628 | QHULL d
- qh_createsimplex: clears qh.num_visible, may be non-zero with 'TRn QJ'
Changes to prompts, warnings, and statistics
- For Delaunay & Voronoi, 's' reports deleted vertices due to facet merging.
They were incorrectly reported as nearly incident points.
- Warn if recompute centrum after constructing hull
- Simplified narrow hull warning and print all digits of cosine.
A narrow hull may lead to a point outside of the hull.
- Print total vertices deleted instead of ave. per iteration (Zdelvertextot)
- Improved tracing for qh_partitionpoint and qh_partitioncoplanar
- Added number of distance tests for checking outer planes (qh_check_maxout)
- Simplified "qhull precision error: Only n facets remain."
- Included 'TRn' in the causes of a premature exit
Changes to documentation
- README.txt: Added quickstart instructions for Visual C++
- rbox: Added example of edge of narrow lens, rbox 1000 L100000 s G1e-6
- Added cross references between options 'o' and 'p'.
- qh-eg.html: added examples comparing 'Qt', 'QJ', and neither 'Qt' nor 'QJ'
eg.15a.surface, eg.15b.triangle, eg.17a.delaunay.2, etc.
- Reorganized and enhanced discussion of precision problems in qh_impre.htm
- Fixed spelling errors [K. Briggs]
- Fixed link errors, validated HTML, and spell checked [HomeSite]
- Removed unnecessary #TOP links
- Added source links to the qh-quick.htm's header and footer
- qh-geom.htm, qh-poly.htm: add links to Voronoi functions in io.c
- src/index.htm: Added how to search libqhull.h for qhull options
- qvoronoi.htm/qdelaun.htm: 'Fc' and 'FN' includes deleted vertices
Changes to URLs
- Added http://www.voronoi.com and http://www.magic-software.com
Changes to code
- qh_qhull: if 'TVn' or 'TCn' do not call qh_check_maxout and qh_nearcoplanar
- reviewed time profile. Qhull is slower. Optimized qh_findbestnew()
- qh_addpoint: Added warning note about avoiding a local minimum
- qh_checkpolygon: report qh.facet_next error if NARROWhull & dist>MINoutside
- qh_findbest: renamed "newfacets" parameter to "isnewfacets" since it is boolT
- qh_findbest/qh_findbestnew: testhorizon even if !MERGING
Otherwise qhull c D6 | qhull Q0 Tv assigns coplanar points
- qh_resetlists: add qh_RESETvisible for qh_triangulate
- qh_findbest: search better facets first. Rewritten.
- qh_findbest: increased minminsearch, always check coplanar facets.
See: RBOX 1000 s Z1 G1e-13 t996564279 | QHULL Tv
- qh_findbestnew: report precision error for deleted cones [rare event]
e.g.: RBOX 1000 s W1e-13 P0 t1001034076 | QHULL d Qbb Qc Tv
- qh_findbesthorizon: search horizon of qh.coplanarset. New.
- qh_findbestsharp: replaced with qh_sharpnewfacets followed by qh_findbestnew
- qh_partitionpoint, Delaunay sites can not be inside. Otherwise points may
be outside upperDelaunay facets yet not near-inside Delaunay facets
See: RBOX s 1000 t993602376 | QHULL C-1e-3 d Qbb FA Tv
- qh_partitioncoplanar: call qh_findbest/qh_findbestnew with qh DELAUNAY
- qh_printlists: format long lines
- qh_printvertex: format long lines
- user.h: tightened qh_WARNnarrow and qh_MAXnarrow. Do not see problems
until they are -1.0.
- user.h: defined qh_DISToutside, qh_SEARCHdist, and qh_USEfindbestnew
- qh_checkfacet: in 3-d, allow #ridges > #vertices. Can get a vertex twice
in a ridge list, e.g, RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv
Changes to FAQ
- Recommended use of triangulated output ('Qt')
Changes to distribution
- Recompiled in Visual C++ 5.0 with optimization (as was version 2.6)
- q_test: Added bad cases for Qhull and tests for new features
Changes to Qhull library
- Added qh_triangulate() to poly2.c. It triangulates the output.
- Added option 'Q11' to copy normals and recompute centrums for tricoplanar facets
'FP' may not print the nearest vertex for coplanar points
Use option 'Q11' when adding points after qh_triangulate()
------------
qhull 3.0 2001/02/11
Changes to distribution
- added qconvex, qdelaunay, qhalf, and qvoronoi
- added qhull-interface.cpp on calling Qhull from C++ [K. Erleben]
- renamed to qhull3.0/.
- added eg/, html/, and src/ directories
Changes to URLs
- MathLab6 qhull: convhulln, delaunayn, griddatan, tsearchn, vororoin [Z. You]
- Wolfram Research wrote a Mathematica interface for qdelaunay [Hinton]
- Geomview moved from www.geom.umn.edu to www.geomview.org [M. Phillips}
- added URLs for tcsh and cygwin to README.txt
Changes to documentation
- reorganized table of contents and renamed qh-man.htm to index.htm
- wrote program documentation, dropped qh-opt.htm and qh-optv.htm
- added quick reference, qh-quick.htm
- reorganized qh-rbox.htm and renamed it to rbox.htm
- split up qh-c.htm for quick navigation
Corrections to code
- fixed type of arg for error message in qh_initqhull_globals [N. Max]
- fixed incorrect initialization of qh MINdenom_1 for scalepoints
- fixed drop dim for 'H Qbk:0Bk:0'. Added qh.feasible_point to qh_projectinput
- qh_WARNnarrow is angle between facet normals. Negate for warning message.
- statistics for Wangle/etc. concerns facet normals. Reworded [E. Voth]
- fixed error message for 'FC v'
- report cospherical points if Delaunay and error in qh_scalelast()
Changes to code
- turn on Pg if (QVn or QGn) and not (Qg or PG)
- turn on Qc if format option 'Fc', 'FP', or 'Gp' (removes warning)
- removed last good facet unless ONLYgood ('Qg').
- added count of non-simplicial or merged facets to 'FS'
- added count of non-simplicial facets to 's' (OK if #vertices==dim)
- added Znonsimplicial and Znowsimplicial to 'Ts'
- allow Mathematica output of dual polytope for halfspace intersection
- added qh_checkflags to globals.c for multiple front ends
- qh_initqhull_globals sets qh.MERGING if qh.MERGEexact
- removed hashentryT. It is no longer used.
Changes to prompts and warnings
- reorganized prompts
- reorganized synopsis for rbox.c
- print warning if 'Fc' or 'FP' with 'd QJ'. Coincident points are unlikely.
- ignore warning if options 'v i Pp'. qvoronoi users may need Delaunay tri.
- reworded warning if 'Pg' and 'QVn' is not a vertex.
- reworded warning for 'Qx Tv', qh_check_points() in poly2.c
- if 'Pp', turn off warning for 'Qbb' without 'd' or 'v'
- in qh_printsummary() of Voronoi and Delaunay, distinguish QVn, QGn, Pdn, PDn
Changes to FAQ
- added FAQ item for nearly flat Delaunay triangles [Z. You]
- added FAQ item for area and volume [R. Konatham]
- added FAQ item for Voronoi diagram of a square [J. Yong]
- edited FAQ item on point location in Delaunay triangles [Z. You]
- added FAQ item on nearly flat Delaunay triangles [Dehghani]
- added FAQ item about halfspace intersection [V. Tyberghein]
- added FAQ item for missing ridges [M. Schmidt]
- added FAQ item about qh_call_qhull [R. Snyder]
- added FAQ item about memory statistics [Masi]
- added FAQ item on meshing non-convex objects
- added FAQ item on MATLAB and Mathematica interface
------------
qhull 2.6 1999/04/19
- fixed memory overwrite (no effect) in qh_initstatistics() [K. Ford]
- added zdoc11 to qh-stat.h#ZZdef for !qh_KEEPstatistics [K. Ford]
- enhanced qh_initqhull_globals() test of qh_RANDOMint and qh_RANDOMmax
- added debugging option to always return qh_RANDOMmax from qh_rand()
- fixed option 'Qr', qh_initialvertices(), to allow a broken qh_rand()
fixed option 'Qr', qh_nextfurthest(), to allow narrow hulls
Option 'Qr' simulates the random incremental algorithm for convex hulls
- added note that qh.num_outside includes coplanar points for narrow hulls
- added FAQ items for triangles/ridges of 3-d Delaunay triangulation[P. Kumar]
- added FAQ item about on-line processing with the Qhull library [O. Skare]
- changed name of option 'Error-roundoff' to 'Distance-roundoff'
------------
qhull 2.6 1998/12/30
- for the unbounded rays of the Voronoi diagram, use a large box [Schmidt]
e.g., 'rbox P4,4,4 P4,2,4 P2,4,4 P4,4,2 10 | qhull v Fv' fails for point 0
while 'rbox P4,4,4 P4,2,4 P2,4,4 P4,4,2 10 c G5 | qhull v Fv' is OK.
- fixed qh_new_qhull() to use outfile/errfile instead of stdout/stderr [Ford]
- clarified COPYING.txt for use in other programs [Archer]
- improved qh_readpoints() error message for incorrect point count.
- added FAQ item for closest triangle to a point [Sminchisescu & Heijting]
- added FAQ item for is a point outside of a facet [Beardsley]
- added FAQ item for visiting facets of the Delaunay triangulation [Heijting]
- added link to Erickson's Computational Geometry Software
- added link to Sharman's HTML version of the comp.graphics.algorithms FAQ
- added link to Owen's Meshing Research Corner
- added note to 'd' about quadratic size of 'rbox 100 l | qhull d' [Kumar]
- added 'about a point' to mentions of halfspace intersection
- added request to qh-code.htm to compute largest empty circle [Hase]
- the DOS window in Windows NT is better than the DOS window in Windows 95
- removed obsolete qh_findfacet() from qh-c.htm [Sminchisescu]
------------
qhull 2.6 1998/8/12
new and modified features
- rbox: added option Mn,m,r to generate a rotated lattice or mesh
- rbox: report error if more than one of 'l', 'x', 'L', 's', or 'M'
Qhull library changes
- added qh_new_qhull() to user.c for calling qhull() from a program [D. Zwick]
rewrote user_eg.c to use qh_new_qhull(). Added qh_QHpointer example.
- added qh_CLOCKtype 2 in user.h to call times() for CPU time [B. Hemkemeier]
- renamed set.c/set.h to avoid conflict with STL's set.h [G. van den Bergen]
can also use '#include ' for Qhull library
fixed errors
- fixed qh_init_B() to call qh_initqhull_mem() once only [D. Zwick]
This only effects Qhull library users of qh_QHpointer.
- fixed qh_mergecycle_all() to check for redundant vertices [J. Nagle]
e.g., 'rbox M3,4 64 | qhull Qc' should report 8 vertices & 48 coplanars
- fixed gmcoord initialization in qh_setfacetplane() for qh.RANDOMdist
- turn off qh.RANDOMdist during qh_printfacetheader()
- fixed error messages for unknown option flags
documentation changes
- added note to FAQ on the Voronoi diagram of cospherical points [H. Hase]
- added note to 'Qu' on furthest-site Delaunay triangulation via convex hull
- added note to 'QJ' about coplanar points on the convex hull of the input
- added note that 'o' and 'FN' list Voronoi regions in site id order [Arvind]
- added links to Fukuda's introduction to convex hulls, etc. [H. Hase]
- added .c and .h source files to web distribution and qh-c.htm [J. Sands]
- documented qh_ZEROdelaunay. Delaunay and Voronoi diagrams do not include
facets that are coplanar with the convex hull of the input sites.
modified code
- replaced computed minnorm in qh_sethyperplane_det with distance test
- removed 'qh rand_seed' since random number generator is independent of qhull
- dropt 'qhull-PPC.sit.bin' from the distribution (out-of-date) [M. Harris]
------------
qhull 2.5 1998/5/4
fixed errors
- removed zero-area Delaunay triangles and furthest-site triangles [I. Beichl]
Zero-area triangles occur for points coplanar with the input's convex hull.
- replaced qh.MINnorm with computed minnorm in qh_sethyperplane_det [J. Nagle]
qh.MINnorm was incorrect for the convex hull of the "teapot" example.
Qhull runs 0-20% slower in 3-d and 4-d.
- allow 'Qg' with furthest-site Delaunay triangulation (may be faster)
- removed extra space in definition of FOREACHmerge_() for Alpha cc [R. LeRoy]
- fixed innerouter type in qh_printvdiagram2 [does not effect code, R. Adams]
documentation changes
- to browse qh-c.htm, set MIME type of .c and .h files to text/html
- added example of 3-d Delaunay triangulation to q-faq.htm
- added Delaunay and Voronoi examples to qh-optv.htm
------------
qhull 2.5 1998/2/4
- added option 'v Fi' for separating hyperplanes of bounded Voronoi regions
- added option 'v Fo' for separating hyperplanes of unbounded Voronoi regions
- option 'Pp' turns off the warning, "initial hull is narrow"
- fixed partial, 3-d Voronoi diagrams (i.e., 'v Fv QVn Tc')
- fixed missing statistics in qh_allstat* [T. Johnson]
- rearranged qh_printvdiagram. Use qh_eachvoronoi to iterate Voronoi ridges.
- added qh_check_points to qh-math.c
qhull 2.5 1998/1/28
- added option 'Fv' to print the Voronoi diagram
- added rbox option 'x' to generate random points in a simplex
- added rbox option 'y' to generate a simplex and random points
- added rbox option 'On' to offset the output
- add unpacking instructions to README.txt
- updated discussion of forced output, 'Po'
- sorted the options alphabetically
- removed __STDC__ check from libqhull.h for VisualC++
- moved qh_markvoronoi from qh_printvoronoi and cleared facet->seen flags
- added facet->seen2 flag for 'Fv'
qhull 2.5 1998/1/16
- fixed initialization of qh.last_low on restart of 'd QJ'
- renamed qh_JOGGLEmax to qh_JOGGLEmaxincrease
- updated URL for Fukuda's cdd program
qhull 2.5 1998/1/12
New or modified features
- added option 'Fx' to print vertices by point id [G. Harris, T. McClendon]
in 2-d, the vertices are printed in counter-clockwise order
for Delaunay triangl., 'Fx' lists the extreme points of the input sites
- added option 'QJ' to randomly joggle input instead of merging facets
- added option 'TO file' to output results to a file. Needed for Windows95.
- added option 'TRn' to rerun Qhull n times. Use to collect joggle statistics
Corrections
- fixed 2-d facet orientation for 'i' and 'o' outputs
- for Mathematica 2.2 ('m') changed %10.8g to %16.8f [A. Zhaxybayev]
- fixed incorrect warning for 'QV0 Qg' in qh_initbuild [B. Wythoff]
- fixed unaccessible statistic if !qh_KEEPstatistics for Wnewvertexmax
- fixed overestimate of qh ONEmerge for point sets outside of
first quadrant and far from the origin
- fixed overestimate of 'Qbb' for point sets far from the origin
- fixed potential overestimate of qh DISTround under 'Qbb'
- fixed 'p' printing coplanar points of unselected facets
- fixed 'Ft' printing centrums unnecessarily in 2-d
Changes to documentation
- wrote internal design documentation (qh-c.htm)
- started frequently asked questions (qh-faq.htm)
- added a section on joggled input to qh-impre.htm
- added joggle example to qh-eg.htm (eg.15.joggle)
- changed q_eg to use 'QJ' instead of 'Q0' were appropriate
- added an example to each of the main options
- added examples to rbox.htm
- added examples to the synopsis
- added a reference to Mucke, et al ['96], Fast randomized point location ...
- added code for printing Delaunay triangles to qh-code.htm [A. Tsui]
- options 'Pdk' and 'PDk' do not drop on equality
Improvements to the code
- reviewed warning messages for Qhull options in qh_initflags
- added warning to 's' if premature exit from 'TCn' or 'TVn'
- 's' prints max distance above/below only if qh.MERGING
- reduced maxoutside in qh_check_bestdist/qh_check_points for 'Rn'
- in post-merging, rebuild centrums of large facets that become small
- lowered cutoff for coplanar facets for ischeckmax/qh_findbest
- removed qh_check_maxout for 'Wn Q0'
- reset tracing after 'TPn' adds point in 4-d and higher
Changes for the Qhull library
- changed qh_setdelaunay to call qh_scalelast if used with 'Qbb' or 'QJ'
Delaunay callers to qh_findbestfacet, qh_addpoint, or qh_findfacet_all
should always use qh_setdelaunay as in user_eg.c
- defined qh.outside_err to check points against a given epsilon [E. Voth]
- added header to user_eg.c to avoid its incorporation into qhull [C. Begnis]
- added qh_nearcoplanar() calls to user_eg.c
only needed if use 'QJ'
- expanded __STDC__ warning message in libqhull.h [C. Begnis]
- renamed qh maxmaxcoord to qh MAXabs_coord
- replaced qh MAXlowcoord with qh MAXabs_coord
- random seed ('QR-n') is reset in qh_initqhull_globals after testing
- replaced 'FO' options "_max-coord/_min-coord" with "_max-width"/qh.MAXwidth
Other changes to Qhull functions
- report error for !bestfacet in qh_findbest (it shouldn't happen) [H. Meuret]
- set newbest in qh_findbest only if bestfacet updated
- renamed facet parameter for qh_findbest
- added maxdist argument to qh_checkpoint
- moved 'FO' output after qh_partitionall
- separated qh_initbuild from qh_qhull
- reinitialize globals modified by qh_buildhull
- moved initialization of qh.GOODvertexp & qh.GOODpointp to qh_initbuild
- separated qh_nearcoplanar from qh_check_maxout
- separated qh_geomplanes from qh_printfacet2geom, etc.
- separated qh_freebuild from qh_freeqhull
- separated qh_outerinner from io.c to return outer and inner planes
- separated qh_distround and qh_detroundoff from qh_maxmin
------------
qhull 2.4 97/4/2
New or modified features
- made 'C-0' and 'Qx' default options. Use 'Q0' to not handle roundoff errors
- removed point-at-infinity from Delaunay/Voronoi.
you no longer need to use 'Qu PDk'
- added 'Qz' to add a point-at-infinity to Delaunay and Voronoi constructions
- added published version of qhull article in ACM Trans Math Software
- ported qhull to Windows95 under Visual C++ and Borland C++
- added 'Ft' for triangulation by adding the centrums of non-simplicial facets
- added 'Gt' to display 3-d Delaunay triangulations with a transparent hull
- changed definition of coplanar point in output to qh min_vertex (see 'Qc')
it was qh MAXcoplanar ('Un') [could make vertices non-coplanar]
- automatically set 'Qi' for options 'd Qc' and 'v Qc'.
- reworded summary ('s') for Delaunay/Voronoi/halfspace.
use 'Fs' and 'FS' for summary statistics.
- for summary 's' of Delaunay/Voronoi, display number of coplanars for facets
if none, display total number of coplanars (i.e., non-vertices)
- input comment is first non-numeric text (previously limited to header)
- added input warning if use 'Qbb' without 'd' or 'v'
- 'Q3' can not be followed with a numeric option
Corrections
- fixed qh_partitioncoplanar() to not drop interior points if 'Qi' is used
- fixed 'FP d' to report distance in point set instead of paraboloid
- fixed qh_findbest() to search all coplanar facets for qh_check_maxout()
Changes to documentation
- added example eg.17f.delaunay.3 to show a triangulation of cospherical sites
- split up qh-opt.htm into multiple pieces
- split off qh-code.htm for Qhull code
- renamed .html files to .htm for Windows95
- rewrote qh-optv.htm on Delaunay triangulation and Voronoi vertices
- added 'man' pages qhull.txt and rbox.txt. These list all the options
- removed 'txt' versions of html files
- added note to 'PDk' about avoiding a 'd' option immediately after a float
- under option 'd', display the triangulation with 'GrD3', not 'GnrD3'
Changes to the Qhull library
- added 'format' argument to qh_printfacetNvertex_nonsimplicial() in io.c
- removed C++ type errors [J. Stern, S. Marino]
- created SETelemt, SETfirstt, etc. for specifying data types.
- use SETelem,etc. for assignments.
- changed setT.maxsize to 'int' to prevent type conversion warnings
- changed FOREACH.. to a comma expression for better code and less warning
- changed qh.vertex_visit and .visit_id to unsigned int to prevent warnings
- changed clock() to qh_CPUclock (user.h)
- qh_init_B() and qh_readpoints() do not set qh.ATinfinity for Delaunay tri.
- qh_setvoronoi_all() sets upper Delaunay facets if qh.UPPERdelaunay is set
- qh_nearvertex() returns distance in dim-1 for qh.DELAUNAY
- removed MSDOS path from qhull_command. Spaces in Win95 tripped qh_setflags
- removed memory.h from qhull_a.h. memset,etc. should be in strings.h
- split qh_prompt into pieces for Visual C++
- added note to qh_addpoint that coordinates can not be deallocated
- added Baker '89 to constrained Delaunay diagrams under Enhancements
please let me know if you try this
- added request for unbounded Voronoi rays to Enhancements
please let me know if you try this
------------
qhull V2.3 96/6/5
- fixed total area of Delaunay triangulation. [A. Enge]
It should ignore facets on the upper-envelope.
- if 'd Qu FA', the total area is summed over the upper-Delaunay triangles
- fixed sign of area for Delaunay triangulations.
- fixed cdd input format for Delaunay triangulation. [A. Enge]
- for cdd input, allow feasible point for halfspaces.
- warning if cdd output format for centrums, halfspace intersections, or OFF.
- print '0' for area ('Fa') if area is not computed for a facet
- option 'QR-n' sets random number seed to n without rotating input
- fixed qh_findbest() to retest coplanar and flipped facets after a restart
- for 'd Qu Ts' collects angle statistics for upper Delaunay facets
Changes to the Qhull library
- expanded user_eg.c for incremental constructions and Delaunay triangulation
- added discussion of incremental construction to qh_man.html#library
- WARNING: The default value of qh ATinfinity was changed from True to False.
A new flag, qh UPPERdelaunay, was defined for 'Qu'.
Please set qh ATinfinity if you explicitly add the point "at-infinity"
Please set qh ATinfinity if you explicitly call qh_projectinput.
Please set qh UPPERdelaunay if you explicitly cleared qh ATinfinity.
Other users do not need to change their code.
Now you can build a Delaunay triangulation without creating a point
"at-infinity". This removes a potential, hard-to-understand error.
qh_readpoints sets qh ATinfinity for options 'd' or 'v' without 'Qu'.
qh_initB sets qh ATinfinity for qh PROJECTdelaunay w/o qh UPPERdelaunay.
qh_projectinput adds a point "at-infinity" only if qh ATinfinity is set.
- added qh_setdelaunay to geom2.c to project points to paraboloid
- added qh_findbestfacet() to poly2.c to replace qh_findfacet()
- removed procedure qh_findfacet(). It does not always work.
- removed NULL option for facet in qh_addpoint(). It does not always work.
- added noupper parameter to qh_findbest.
- added search of upperdelaunay facets to qh_findbest()
- allowed qh_findbest() to start with a flipped or upperdelaunay facet
- removed qh_nonupper() -- it is no longer needed
- allow space at end of options
- fixed qh_projectinput for furthest-site Delaunay (qh PROJECTdelaunay 'd Qu')
- added voids to procedure declarations with empty parameter lists
------------
qhull V2.3 96/3/25
- fixed missing qh_check_maxout when coplanar points and no merged facets.
- fixed qh_freeqhull/allmem (e.g., if qh_NOmem) [only custom code] [E. Voth]
- fixed qh_freeqhull to free qh interior_point [E. Voth]
- fixed main() to free all of memory if qh_NOmem. Include "mem.h" [E. Voth]
- reset f.newcycle link in qh_mergecycle_all [E. Voth]
- fixed false error if 'Tc', coplanar points, and a narrow hull
- turn off 'Rn' when computing statistics, checking code, or tracing code
- removed ={0} from global.c and stat.c to reduce compiler warnings
- changed Makefile dependences to $(HFILES) for all but unix.o, set.o, mem.o
- pulled out qh_printpointid and reordered qh_pointid [E. Voth]
- removed some compiler warnings
- moved 'FO' print of options to just before qh_buildhull
- changed 'FO' to list difference from -1 for _narrow-hull
------------
qhull V2.2 96/2/15
- detect narrow initial hulls (cosine of min angle < qh_MAXnarrow in user.h).
Write warning if cosine < qh_WARNnarrow in user.h. If narrow (qh NARROWhull),
partition coplanar points as outside points and delay coplanar test to end.
Needed for RBOX 1000 L100000 s G1e-6 t995127886 | QHULL Tv
See 'limitations' in qh-impre.html for further discussion.
- corrected some confusions between 'FV' and 'Fv' in qh-opt.html
- fixed initialization error for small Voronoi diagrams (e.g., [0,0], [1,0], [0,1]) [J. Velez]
- fixed bad return from qh_mindiff in geom2.c
- for initial hull, first process facet with furthest outside point (qh_furthestnext)
- added facet->notfurthest flag for recomputing furthest point
- added check for __STDC__ (needs ANSI C) [E. Voth]
- reduced warning messages from [E. Voth]. e[1] in setT still reports a warning.
- added a cube to the discussion of option 'v' (Voronoi) in qh-opt.html [J. Velez]
- added notes about adjacent vertices to "Calling Qhull" in qh-man.html [R. Lewis & J. Velez]
- added note about 'lines closer' when viewing 3-d Delaunay triangulations [P. Kallberg]
- added option 'Q9' to always process furthest of furthest outside points.
- removed option 'Pp' from q_eg and qh-eg.html.
------------
qhull V2.2 95/12/28
- added option 'Qbb' to scale the last coordinate to [0,m] (max prev coord).
This reduces roundoff errors for Delaunay triangulations with integer coordinates.
- changed option 'Qu d' to print out the furthest-site Delaunay triangulation
Use options 'Qu d PD2' to compute the normal 2-d Delaunay triangulation without
the point at infinity.
- added notes to the documentation of option 'd'
- added notes to limitations of how Qhull handles imprecision
- added warning if options 'FP', 'Fc', or 'Gp' without option 'Qc' or 'Qi'
- added note to options 'PDk:n' and 'Pdk:n' that closest facet is returned if none match
- added check that 'Qbk' and 'QBk' does not invert paraboloid for 'd'
- added notes that qh_findfacet and qh_addpoint require lifted points for Delaunay triangulations
- fixed 'rbox s 5000 W1e-13 D2 | qhull d Qcu C-0 Qbb'
- fixed option 'QbB' (qh SCALEpoints was not set)
- fixed minor confusion between 'Gc' (print centrums) and 'Gp' (print points)
- rewrote qh_findbestnew for upper convex hull, Delaunay facets
- changed option name for 'Gp' from 'Gcoplanar' to 'Gpoints'
- changed "nearest" facet for 'Pdk' to threshold - normal
- reworked qh GOODclosest for 'Qg'
- added note that 'Qg' does not always work
- recorded option 'C-0' as "_zero-merge" in option 'FO'
- refined qh DISTround in qh_maxmin/geom2.c for Delaunay triangulations
qhull V2.2 95/12/4
- Version 2.2 fixes an important bug in computing Delaunay triangulations
and convex hulls with edges sharper than ninety degrees. The problem
occurs when processing a point at a sharp edge. A directed search can
not be used for partitioning because one side may hide facets from the
other side. The new lens-shaped distribution for rbox demonstrates the
problem. For example, 'rbox 100 L3 G0.5 s | qhull Tv' fails for Version 2.1.
O. Schramm found the bug when computing the Delaunay triangulation of points
near an outside edge.
I rewrote qh_findbest and related functions. Qh_findbest
uses an exhaustive test for sharp edges (qh_findbest_sharp).
Qh_findbest avoids the upper convex hull of Delaunay triangulations.
Options 'd' and 'v' no longer assign coplanar points to the upper convex hull.
Qh_check_maxout tests near-inside points. It ignores fully inside points.
When done, it removes near-inside points from the coplanar sets.
If you use qh_addpoint or qh_findbest, please review the function headers.
They do not work for lens-shaped hulls for arbitrary facets. They do work for
Delaunay triangulations.
Changes to options for V2.2
- added 'Qu' for computing the furthest-site Delaunay triangulation (upper hull)
and furthest-site Voronoi vertices.
- added 'FP' to print nearest vertex for coplanar points
- added coplanar count to 'Fs' and 's'
- added number of similar points to summary for Delaunay/Voronoi
- Option 'Qc' is no longer necessary when merging.
- 'o' format for Voronoi vertices ('v') generates "0" lines for similar points
- 'QRn' for Delaunay ('d' or 'v') now rotates about the Z axis (see qh_init_B).
Otherwise Qhull does not identify the upper hull
- removed option 'Qa' for "all points outside". In V2.1 it was automatically
set for 'd'. Even though it was a bad idea, it revealed the above bug.
- for option list ('FO'), added version, values for one-merge, maxpos, maxneg,
and near-inside, and flags for zero-centrum
- optimized 'C-0' and 'Qx'. These options ("zero-centrum") test vertices
instead of centrums for adjacent simplicial facets.
- if 'Tv', report number of points that are not verified due to qh_findbest
- Option 'Q8' ignores near-inside points.
rbox 95/12/3
- added lens distribution ('Ln') It may be used with 's', 'r', 'Wn', and 'Gn'
- removed default point count except for the test case, 'Dn'
- divided main() of rbox.c into sections
Documentation changes for V2.2
- added examples for lens distribution and furthest-site Delaunay triangulation
and renumbered the examples for q_eg
- described facet orientation in 'data structure' section [P. Soikkonen]
- added notes to qh-man.html/"What to do if something goes wrong"
- added note about using 'Tv' to verify the results [O. Schramm]
- expanded definition of f_r in Performance section [S. Grundmann]
- noted that Geomview display of a Voronoi diagram adds extra edges
for unbounded Voronoi cells
- rewrote error "convexity constraints may be too strong" [D. Newland]
- added limitations section to "Imprecision in Qhull"
- added note about zero-area facets to 'Imprecise convex hulls' in qh-impre.html
- added note to 'Qi' that it does not retain coplanar points
- added note that option 'Q5' may be used if outer planes are not needed
- added note to README.txt about Irix 5.1 [C. Goudeseune]
- added code fragment for visiting Voronoi vertices to "Calling Qhull" [M. Downes]
- added note about qh_addpoint() to "Calling Qhull" [M. Downes]
Errors fixed for V2.2
- use qh_sethyperplane_gauss if 3-d or 4-d norm is less than qh MINnorm
- count Zcentrumtests if qh_NOstat
- reversed sign convention for qh_sethyperplane_gauss
it was opposite to qh_sethyperplane_det
this effects qh_determinant and qh_detsimplex
- fixed error in qh_findgood_all with multiple restrictions, e.g., 'QVn Pdk'
- fixed call to qh_clearcenters for qh_produce_output
- in qh_errexit, report p0 if last furthest point
Changes for users of the Qhull library
- user code needs to define qh_version (see user_eg.c)
- merged initialization code into qh_init_A and qh_init_B [M. Mazzario]
old code works as before.
qh_initflags also sets qh qhull_command for qh_initthresholds
redid initialization for user_eg.c
- simplified user_eg.c. It computes the convex hull of a cube.
- added qh_setvoronoi_all in poly2.c to compute Voronoi centers
added related note to call_qhull
- added qh_findfacet to use in place of qh_findbest
- added qh_nearvertex to return nearest vertex in facet to point
- redid notes on multiple, concurrent calls in call_qhull/user.c
- changed BoolT to unsigned int (prevent implicit enum conversion warnings)
- added upperdelaunay to facetT. It indicates a facet of the upper convex hull.
- converted qhull-PPC.sit for CodeWarrior 7
Code changes for V2.2
- simplified calls to setjmp() for Cray J916 [Salazar & Velez]
- replaced fprintf(fp,string) with fputs in io.c
- 'qh num_coplanar' removed (too expensive and not used).
- added numcoplanars to qh_countfacets()
- added min norm to qh_normalize2(). qh_normalize() wasn't changed
- removed type casts from qh_point and qh_pointid [Salazar & Velez]
- account for roundoff error in detecting upper convex hull (qh ANGLEround).
- post merging uses qh_findbestnew for partitioning
- qh_findbestnew for qh_partitioncoplanar goes to best facet
- 'Qm' always processes points above the upper hull of a Delaunay triangulation
- GOODvertex initialized with qh_findbestnew instead of qh_findbest
- for 'v', qh_facetcenter returns furthest-neighbor vertex if 'Qu'
- added test for qh feasible_point if use 'Fp' and qh_sethalfspace_all
- reviewed Sugihara's algorithm for topologically robust beneath-beyond
- on error, report if qhull in post-merging or has completed
- if tracing, option 'FO' and qhull command always printed
- added current furthest point ("during p%d") to 'T-1' events
- added 'TWn' tracing for vertices of new facets (qh_setfacetplane)
- added 'TWn' tracing for vertices in an output facet (qh_check_maxout)
- reorganized split between poly/poly2.c and geom/geom2.c
- reordered object files in Makefile
------------
qhull V2.1 95/9/25
- converted qhull.man to html format, many edits
- referenced Shewchuk's triangle program and Schneiders' Mesh Generation page
- added option 'Qa' to force all points outside
automatically set for "precise" Delaunay or Voronoi [Salazar & Velez]
it is turned off by merging, 'Wn', 'Qc' or 'Qi'
- added coplanar points to option 'FN'
- moved option 'FO' to include default precision options
- changed default random number generator to qh_rand in geom2.c (user.h)
other code changes
- fixed option comment Pdrop-facets-dim-less, Qbound-dim-low, QbBound-unit-box
- defined ptr_intT for converting 64-bit ptrs to 'unsigned long' [D. Bremner]
- defined setelemT to distinguish actual size from pointers [D. Bremner]
use either e[...].p or e[...].i (user-level code should use set.h macros)
- changed %x to %p in format statements for pointers [D. Bremner]
- added test of REALmax,etc. to qh_maxmin [H. Poulard]
- added type parameter to qh_memalloc_() macro for type conversion
- added type conversion to qh_memalloc() calls where missing
- added type conversion to calls into set.c that return void*
other documentation changes:
- new URLs for graphics images
- fixed comment for facetT.neighbors in libqhull.h [P. Soikkonen]
- changed recommendations for precision errors in qh_printhelp_degenerate()
- added recommendation for 'V0' (facet is visible if distance >= 0)
- added note about 'long double' to user.h [S. Grundmann]
- added note about zero area Delaunay triangles for the 'v' option
- added note about locating Delaunay triangles to option 'd' [A. Curtis]
- added note that coplanar vertices correspond to duplicate points for 'd'
- added note about option 'd' automatically setting 'PDk' (lower convex hull)
- added note about precision errors to option 'd' [many users]
- added note about qh_findbest() to the Qhull library section [L. Lai]
- 'make install' renames qhull.man to qhull.1 for Unix [M. Phillips]
- renamed README, etc. to *.txt to match WWW conventions [D. Cervone]
------------
qhull V2.1 7/10/95
- in 2-d, 'v o' lists the vertex at infinity in order [R. Critchlow]
- it used to always list the vertex at infinity ("0") first
- rewrote description of 'v' option (Voronoi vertices and 2-d diagrams)
- added 'PFn' for printing facets whose area is at least 'n' [D. Holland]
- prefixed 'Q',etc. to the 'Q',etc. options in the long help prompt
- fixed references to 'Fv' and 'FV' options under option 'Hn,n,n'
- updated reference to cdd,
- in set.c, added some missing type coercions for qhmem.tempstack
qhull V2.1 6/12/95
- replaced qhull.ps with qhull-2.ps (paper submitted to ACM TOMS)
- use BUFSIZ for setvbuf for Power Macintosh
- number of good facets printed if QVn, QGn, Pd, or PD
- added Makefile for Borland C++ 4.02 with Win32 [D. Zwick]
- added note to Enhancements section of qhull.1 about constrained
Delaunay triangulations [T. Rasanen]
qhull V2.1 6/7/95
- fixed qh_facetarea_simplex() for non-simplicial facets [L. Schramm]
- fixed cast in qh_point and qh_pointid for 64-bit architectures
- fixed URL for Amenta's list of computational geometry software
- fixed cast in qh_meminitbuffers for qhmem.freelists
- added test for !qh half_space in qh readpoints
- clarified options for qh_printhelp_singular()
- discussed non-simplicial facet area under option 'Fa' in qhull.1
qhull V2.1 6/3/95
- home page for Qhull and new descriptions for the Qhull examples
http://www.qhull.org
- changed SIOUX buffering for Power Macintosh. It runs fast now.
added a project file for Metrowerk's C
- note in README about compiling qhull on the PC
qhull V2.1 beta 5/15/95
======= main changes ========
- added halfspace intersection ('Hn,n,n')
- facet merging is better, especially for high dimensions
- added 'Qx' for exact merges of coplanar points and precision faults
- facet merging is faster, especially for high dimensions.
e.g., convex hull of the 8-d hypercube is seven times faster
- added 'F' output formats for printing each aspect of the convex hull
- format 'Fa' computes facet areas, total area, and total volume
- format 'FO' writes a descriptive list of selected options to stderr
- moved all customization options to user.h
- changed the default precision to 'double' since it's needed for Delaunay.
using 'float' is faster and takes less space (REALfloat in user.h)
- option 'Qm' is no longer important for facet merging
- removed need for 'Qs' by selecting initial simplex with pos. determinants
- renamed 'Qv' to 'Q7' since virtual memory does not work well for qhull
- Qhull is available for the Power Mac (no graphical output)
====== other new and modified options ===========
- changed default MINvisible ('Vn') to a multiple of premerge_centrum ('C-n')
- added 'Un' option to set width of facet for coplanar points.
This replaces the previous rules for determining coplanar points.
- changed default MINoutside ('Wn') to twice MINvisible ('Vn')
- Geomview output adjusts point radii for MINvisible 'Vn'
- the input format allows the number of points to precede the dimension
- options 'v' 'd' 'FAn' and 'FMn' record good facets ('Pg')
- added 'Fd' and 'FD' options for homogeneous coordinates in cdd format
- in rbox, added 'h' flag to generate homogeneous coordinates in cdd format
- option 'PAn' prints out the n facets with the largest area
- option 'PMn' prints out the n facets with the most merges
- option 'Po' under tracing ('Tn') no longer tries to write erroneous facets
- option 'TCn' only prints the old 'visible' facets for 'f'
- 'TFn' reports intermediate results when post-merging
- option 'Ts' with option 'TFn' prints intermediate statistics
- the message for 'Tv' reports if it is checking outer planes
- 'Tz' sends stderr output to stdout
- added 'Q1' to ignore angle when sorting merges (merges are worse)
- added 'Q2' to not perform merges in independent sets (merges are worse)
- added 'Q3' to not remove redundant vertices (faster)
- added 'Q4' to avoid merges of old facets into new facets (does worse)
- added 'Q5' to skip qh_check_maxout (faster, but less accurate)
- added 'Q6' to skip pre-merge of concave and coplanar facets
- added 'Qv' for testing vertex neighbors for convexity (needs merge option)
- added warning if mix Geomview output with other outputs ('Po' turns off)
- options 'o v' for 3-d and higher sort the Voronoi vertices by index
======= documentation =======
- rewrote the introduction and precision sections
- added a section on performance
- added an example on halfspace intersection
- installed examples of Qhull in
======= Makefile, user.h, and messages =======
- Makefile calls ./qhull, ./rbox, and prints short prompt for qhull
- added new statistics, e.g., for buildhull
- changed default qh_RANDOMtype to RAND_MAX with rand()
- added comment about numeric overflow to printhelp_singular
- reorganized the code to improve locality of reference
- option in mem.h (qh_NOmem) to turn off memory management in qhull
- option in user.h (qh_NOtrace) to turn off tracing in qhull
- option in user.h (qh_NOmerge) to turn off merging in qhull.
- use this instead of redefining qh_merge_nonconvex in user.c
- simplified user_eg.c. See qh_call_qhull() in user.c for the full version
======== bug fixes ============
- fixed error in number of points for 'rbox 100 r' (odd distribution)
- fixed performance error in qh_degen_redundant_neighbors
- qh_partitionpoint now sets facet->maxoutside for first outside point
- fixed performance error in partitioning when merging a large, regular cone
- removed memory leak in qh_appendmergeset
- removed double free of qh line under errors in qh_readinput()
- forcing output on error ('Po') fixed for options 'n' 'o' 'i' 's'
- fixed optimization error on HP machines [fprintf(... *p++)]
======== changes to libqhull.h for user code =======
- qh_collectstatistics and qh_printstatistics removed from libqhull.h.
should use qh_printallstatistics instead
- qh_findbest uses boolT for newfacets
- added qh_findbestnew for non-simplicial facets. qh_findbest is
too slow in this case since it needs to look at many nearly coplanar
facets.
- renamed qh_voronoi/qh_centrum to qh_ASvoronoi, qh_AScentrum
- changed facet->id to 32-bits, added new flags for merging
- added facet->f for facet pointers while merging and for facet area
- added dfacet/dvertex for printing facets/vertices while debugging
- added qh_produce_output and qh_printsummary
======== changes to code ==========
- moved qh_setfacetplane from qh_makenewfacets to qh_makenewplanes
- added qh_setfree2, qh_setcompact, and qh_setduplicate to set.c
- qh_findgooddist returns list of visible facets instead of setting global
- in qh_check_maxout, inside points may be added to coplanar list.
- qh_findbestnew used for qh_partitionall. It is faster.
- in qh_findbest, changed searchdist to MINvisible+max_outside+DISTround.
MINvisible is the default MAXcoplanar.
- cleaned up list management via qh_resetlists
- uses facet->dupridge to indicate duplicated ridges instead of ->seen
- qh_buildtracing records CPU time relative to qh hulltime instead of 0
========== changes to merging =======
- many performance improvements, especially in high-d.
- when merging, qh_findbest and qh_findbestnew stops search at qh_DISToutside
- vertex neighbors delayed until first merge
- post merges reported every TFn/2 merges
- vertex merging turned off in 7-d and higher (lots of work, no benefit).
vertex merging moved to qh_qhull_postmerging in 6-d.
- replaced qh min_vertex with MAXcoplanar for determining coplanarity
- pick closest facets to merge in duplicate ridge instead of flip/flip
(see qh_matchduplicates in poly2.c)
- optimize merge of simplex into a facet
- optimize merge of a "samecycle" of facets into a coplanar horizon facet
- cleaned up qh_forcedmerges/qh_flippedmerges and removed facet->newmerge
- rewrote qh_merge_degenredundant with separate queue
- qh_facetdegen replaced by facet->degenredun
- flipped neighbors no longer merged in preference to flip/non-flip pairs
- removed angle argument from qh_merge_degenredundant and qh_mergefacet
only used for tracing
- getmergeset_initial had extra test of neighbor->simplicial
- ridge->nonconvex is now set on only one ridge between non-convex facets
- moved centrum deletion to qh_updatetested
- qh_isnewmerge(facet) changed to facet->newmerge (removed NEWmerges)
- qh_findbestneighbor reports correct distance even if testcentrum
- added hull_dim factor to qh_BESTcentrum
- removed horizon preference in qh_merge_nonconvex (qh AVOIDold)
- facet->keepcentrum if qh WIDEfacet or qh_MAXnewcentrum extra vertices
------------
qhull V2.02 1/25/95
- rbox 'z' prints integer coordinates, use 'Bn' to change range
- fixed rare bug in qh_check_maxout when qh_bestfacet returns NULL
- fixed performance bug in findbestneighbor, should be + BESTnonconvex
- renamed 'notgood' flag in 'f' option to 'notG' flag (caused confusion)
- changed qh.hulltime to (unsigned) to prevent negative CPU times
- added random perturbations to qh_getangle under the 'Rn' option
- reviewed the documentation and enhancement list
- added discussion of how to intersect halfspaces using qhull
- replaced expression that caused incorrect code under an old version of gcc
- added buffer after qh.errexit in case 'jmp_buf' has the wrong size
- rewrote qh_printhelp_singular for lower-dimensional inputs
- rewrote qh_printhelp_degenerate
- added options for qh_RANDOMint in qhull_a.h
- changed time format for 'TFn' to %02d
------------
qhull V2.01 6/20/94
- fixed bug in qh_matchnewfacets that occured when memory alignment makes
facet->neighbors larger than necessary.
- fixed bug in computing worst-case simplicial merge of angle coplanar
facets (ONEmerge). This decreases (...x) in printsummary.
qhull V2.01 6/17/94
- added recommendation for 'Qcm' to documentation and help prompts
- added an input warning to qh_check_points ('Tv') if coplanars and no 'Qc'
- qh_partitionpoint: always counts coplanar partitions (Zcoplanarpart)
- rewrote qh_printhelp_degenerate to emphasize option 'C-0'
- For Geomview output, roundoff is not needed when printing the inner and
outer planes. This improves Geomview output for the 'Rn' option.
- For Geomview output without coplanar points or vertices, qh_GEOMepislon
is not needed. This removes the edge gap when displaying a Voronoi cell.
- For Geomview output 'Gp', direct vertices to the interior point
instead of the arithmetic center of the displayed vertices.
qhull V2.01 6/11/94
- if pre-merge, 'Qf' is automatically set. Otherwise an outside point may
be dropt by qh_findbest(). This slows down partitioning.
- always use 'Qc' if merging and all facet->maxoutside's must be right.
Otherwise distributions with many coplanar points may occassionally
miss a coplanar point for a facet. This is because qh_findbest, when
called by qh_check_maxout, can become stuck at a local maximum if
the search is started at an arbitrary facet. With 'Qc', the search
is started from a coplanar facet. For example,
rbox 1000 W8e-6 t | qhull C-0 Tv
will (rarely) report that a facet->minoutside is incorrect
- option 'Pp' turns off "Verifying" message for 'Tv'
- added qh_copynonconvex to qh_renameridgevertex (fixes rare error)
- 'rbox tn' sets random seed to n
- 'rbox t' reports random seed in comment line
- qh_errexit reports rbox_command | qhull_command and 'QR' random seed
- added additional tracing to bestdist and setfacetplane
- in qh_checkconvex, need to test coplanar against 0 instead of -DISTround
- in qh_checkconvex, always test centrums if merging. The opposite
vertex of a simplicial facet may be coplanar since a vertex of
a simplicial facet may be above the facet's hyperplane.
- fixed error handling in qh_checkconvex when merging
- in qh_printsummary, one merge ratio not printed if less than 'Wn'
- documented that 'Tv' verifies all facet->maxoutside
qhull V2.01 6/2/94
- 's' prints summary to stderr
- multiple output formats printed in order to stdout
- added statistic for worst-case distance for merging simplicial facets
can not hope for a better "max distance above/below facet"
print factor for "max distance.."/"merge simplicial" in printsummary
- fixed error in scaling input with min/max reversed ('Qb0:1B0:-1')
- fixed error in scaling if project & Delaunay & scale ('d Qb0:0B1:0b2:0')
- user_eg.c: qh_delpoint removed since it does not always work
- user_eg.c now works for either convex hull or Delaunay triangulation
- added PROJECTdelaunay for Delaunay triangulations and Voronoi diagrams
with libqhull.a and user_eg.c
- user_eg.c: if project or scale input, need to copy points
- user_eg.c: default just defines main, added fprintf's for qh_errprint etc.
- qh_gausselim: a 0 pivot no longer zeros the rest of the array,
need the remaining elements for area computation
- qh_qhull: restore cos_max, centrum_radius at end of POSTmerging
- qh_checkflipped with !allerror is >=0.0 instead of >0.0
- removed -Wall from gcc due to unnecesssary "warning: implicit declaration"
- renamed 'new' variables and fields to allow compilation by g++
- added README notes on C++, and "size isn't known"
- updated manual on 'Qg' with coplanar facets and no merging ('rbox c D7')
'Qg Pg' and 'Pg' produce different results because of precision problems
------------
Converting from qhull 1.01 to qhull 2.00
- 'qhull An' is now 'qhull Wn'
option 'Wn Po' is faster but it doesn't check coplanars
- 'qhull g' is now 'qhull G', and the output formats are different
- 'qhull c' is now 'qhull Tc'
- 'qhull f' is now 'qhull Qf'
- 'qhull o' is now 'qhull Po'
- 'qhull b' is now always done
- qhull and rbox now use floats, change REALfloat in libqhull.h for doubles
- qhull 2.00 fixes several initialization errors and performanace errors
e.g., "singular input" on data with lots of 0 coordinates
- 'rbox b' is now 'rbox c G0.48'
- all rbox distributions are now scaled to a 0.5 box (use 'Bn' to change)
- rbox now adds a comment line. This may be removed by 'rbox n'
- 'rbox r s Z G' no longer includes the positive pole
- no changes to the Macintosh version
qhull V2.00 5/23/94
- if force output ('Po'), facet->maxoutside= 'Wn' since coplanars not updated
convexity checked if precision problems or verify ('Tv')
- if merging, new facets always checked for flipped orientation
- a facet is visible (findhorizon) under 'Qm' if distance > max_vertex
- if using 'Qm' then min. outside is max_vertex instead of max_outside
- default is random()/srandom() in qhull_a.h, checked in initqhull_globals
- created internal strtod since strtod may skip spacing after number
- removed lower bound (1.0) for qh maxmaxcoord
- divzero needs to handle 0/0 and large/small
- decreased size of precise vertices
- need to initialize qh MINdenom_1 for scalepoints
- added factor of qh maxmaxcoord into DISTround (needed for offset)
- 'Rn' perturbs distance computations by random +/-n
- check_points needs an extra DISTround to get from precise point to computed
- rewrote some of the IMPRECISION section in qhull.man
- added the input format to the qhull prompt
- moved include files to qhull_a.h since some compilers do not use float.h
- added qhull.1 and rbox.1 since SGI does not ship nroff
- reduced cutoff for printpointvect
- use time for qhull random seed only if QR0 or QR-1
- radius of vertices and coplanar points determined by pre-merge values
qhull V2.00 5/12/94
- facet2point (io.c) used vertex0 instead of vertex1
- can't print visible facets after cone is attached
- shouldn't check output after STOPcone (TCn)
- statistic 'Wminvertex' and 'Wmaxoutside' only if MERGING or APPROXhull
- 'make doc' uses lineprinter format for paging
- warning if Gpv in 4-d
qhull V2.b05 5/9/94
- decreased size of precise vertices
- precise facets in 2-d print hyperplanes
- accounted for GOODpoint in printsummary
- added IMPRECISION section to qhull.man
- 'Qg' does work in 7-d unless there's many coplanar facets
diff --git a/src/libqhull/global.c b/src/libqhull/global.c
index d3c1ede..147cf42 100644
--- a/src/libqhull/global.c
+++ b/src/libqhull/global.c
@@ -1,2127 +1,2129 @@
/* ---------------------------------
global.c
initializes all the globals of the qhull application
see README
see libqhull.h for qh.globals and function prototypes
see qhull_a.h for internal functions
Copyright (c) 1993-2014 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/global.c#15 $$Change: 1490 $
- $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $
+ $Id: //main/2011/qhull/src/libqhull/global.c#17 $$Change: 1709 $
+ $DateTime: 2014/03/26 22:27:14 $$Author: bbarber $
*/
#include "qhull_a.h"
/*========= qh definition -- globals defined in libqhull.h =======================*/
int qhull_inuse= 0; /* not used */
#if qh_QHpointer
qhT *qh_qh= NULL; /* pointer to all global variables */
#else
qhT qh_qh; /* all global variables.
Add "= {0}" if this causes a compiler error.
Also qh_qhstat in stat.c and qhmem in mem.c. */
#endif
/*----------------------------------
qh_version
version string by year and date
the revision increases on code changes only
notes:
change date: Changes.txt, Announce.txt, index.htm, README.txt,
qhull-news.html, Eudora signatures, CMakeLists.txt
change version: README.txt, qh-get.htm, File_id.diz, Makefile.txt
change year: Copying.txt
check download size
recompile user_eg.c, rbox.c, libqhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c, testqset.c
*/
const char *qh_version = "2012.1 2012/02/18";
/*---------------------------------
qh_appendprint( printFormat )
append printFormat to qh.PRINTout unless already defined
*/
void qh_appendprint(qh_PRINT format) {
int i;
for (i=0; i < qh_PRINTEND; i++) {
if (qh PRINTout[i] == format && format != qh_PRINTqhull)
break;
if (!qh PRINTout[i]) {
qh PRINTout[i]= format;
break;
}
}
} /* appendprint */
/*---------------------------------
qh_checkflags( commandStr, hiddenFlags )
errors if commandStr contains hiddenFlags
hiddenFlags starts and ends with a space and is space deliminated (checked)
notes:
ignores first word (e.g., "qconvex i")
use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
see:
qh_initflags() initializes Qhull according to commandStr
*/
void qh_checkflags(char *command, char *hiddenflags) {
char *s= command, *t, *chkerr; /* qh_skipfilename is non-const */
char key, opt, prevopt;
char chkkey[]= " ";
char chkopt[]= " ";
char chkopt2[]= " ";
boolT waserr= False;
if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
qh_fprintf(qh ferr, 6026, "qhull error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"", hiddenflags);
qh_errexit(qh_ERRinput, NULL, NULL);
}
if (strpbrk(hiddenflags, ",\n\r\t")) {
qh_fprintf(qh ferr, 6027, "qhull error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"", hiddenflags);
qh_errexit(qh_ERRinput, NULL, NULL);
}
while (*s && !isspace(*s)) /* skip program name */
s++;
while (*s) {
while (*s && isspace(*s))
s++;
if (*s == '-')
s++;
if (!*s)
break;
key = *s++;
chkerr = NULL;
if (key == 'T' && (*s == 'I' || *s == 'O')) { /* TI or TO 'file name' */
s= qh_skipfilename(++s);
continue;
}
chkkey[1]= key;
if (strstr(hiddenflags, chkkey)) {
chkerr= chkkey;
}else if (isupper(key)) {
opt= ' ';
prevopt= ' ';
chkopt[1]= key;
chkopt2[1]= key;
while (!chkerr && *s && !isspace(*s)) {
opt= *s++;
if (isalpha(opt)) {
chkopt[2]= opt;
if (strstr(hiddenflags, chkopt))
chkerr= chkopt;
if (prevopt != ' ') {
chkopt2[2]= prevopt;
chkopt2[3]= opt;
if (strstr(hiddenflags, chkopt2))
chkerr= chkopt2;
}
}else if (key == 'Q' && isdigit(opt) && prevopt != 'b'
&& (prevopt == ' ' || islower(prevopt))) {
chkopt[2]= opt;
if (strstr(hiddenflags, chkopt))
chkerr= chkopt;
}else {
qh_strtod(s-1, &t);
if (s < t)
s= t;
}
prevopt= opt;
}
}
if (chkerr) {
*chkerr= '\'';
chkerr[strlen(chkerr)-1]= '\'';
qh_fprintf(qh ferr, 6029, "qhull error: option %s is not used with this program.\n It may be used with qhull.\n", chkerr);
waserr= True;
}
}
if (waserr)
qh_errexit(qh_ERRinput, NULL, NULL);
} /* checkflags */
/*---------------------------------
qh_clear_outputflags()
Clear output flags for QhullPoints
*/
void qh_clear_outputflags(void) {
int i,k;
qh ANNOTATEoutput= False;
qh DOintersections= False;
qh DROPdim= -1;
qh FORCEoutput= False;
qh GETarea= False;
qh GOODpoint= 0;
qh GOODpointp= NULL;
qh GOODthreshold= False;
qh GOODvertex= 0;
qh GOODvertexp= NULL;
qh IStracing= 0;
qh KEEParea= False;
qh KEEPmerge= False;
qh KEEPminArea= REALmax;
qh PRINTcentrums= False;
qh PRINTcoplanar= False;
qh PRINTdots= False;
qh PRINTgood= False;
qh PRINTinner= False;
qh PRINTneighbors= False;
qh PRINTnoplanes= False;
qh PRINToptions1st= False;
qh PRINTouter= False;
qh PRINTprecision= True;
qh PRINTridges= False;
qh PRINTspheres= False;
qh PRINTstatistics= False;
qh PRINTsummary= False;
qh PRINTtransparent= False;
qh SPLITthresholds= False;
qh TRACElevel= 0;
qh TRInormals= False;
qh USEstdout= False;
qh VERIFYoutput= False;
for (k=qh input_dim+1; k--; ) { /* duplicated in qh_initqhull_buffers and qh_clear_ouputflags */
qh lower_threshold[k]= -REALmax;
qh upper_threshold[k]= REALmax;
qh lower_bound[k]= -REALmax;
qh upper_bound[k]= REALmax;
}
for (i=0; i < qh_PRINTEND; i++) {
qh PRINTout[i]= qh_PRINTnone;
}
if (!qh qhull_commandsiz2)
qh qhull_commandsiz2= (int)strlen(qh qhull_command); /* WARN64 */
else {
qh qhull_command[qh qhull_commandsiz2]= '\0';
}
if (!qh qhull_optionsiz2)
qh qhull_optionsiz2= (int)strlen(qh qhull_options); /* WARN64 */
else {
qh qhull_options[qh qhull_optionsiz2]= '\0';
qh qhull_optionlen= qh_OPTIONline; /* start a new line */
}
} /* clear_outputflags */
/*---------------------------------
qh_clock()
return user CPU time in 100ths (qh_SECtick)
only defined for qh_CLOCKtype == 2
notes:
use first value to determine time 0
from Stevens '92 8.15
*/
unsigned long qh_clock(void) {
#if (qh_CLOCKtype == 2)
struct tms time;
static long clktck; /* initialized first call */
double ratio, cpu;
unsigned long ticks;
if (!clktck) {
if ((clktck= sysconf(_SC_CLK_TCK)) < 0) {
qh_fprintf(qh ferr, 6030, "qhull internal error (qh_clock): sysconf() failed. Use qh_CLOCKtype 1 in user.h\n");
qh_errexit(qh_ERRqhull, NULL, NULL);
}
}
if (times(&time) == -1) {
qh_fprintf(qh ferr, 6031, "qhull internal error (qh_clock): times() failed. Use qh_CLOCKtype 1 in user.h\n");
qh_errexit(qh_ERRqhull, NULL, NULL);
}
ratio= qh_SECticks / (double)clktck;
ticks= time.tms_utime * ratio;
return ticks;
#else
qh_fprintf(qh ferr, 6032, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user.h\n");
qh_errexit(qh_ERRqhull, NULL, NULL); /* never returns */
return 0;
#endif
} /* clock */
/*---------------------------------
qh_freebuffers()
free up global memory buffers
notes:
must match qh_initbuffers()
*/
void qh_freebuffers(void) {
trace5((qh ferr, 5001, "qh_freebuffers: freeing up global memory buffers\n"));
/* allocated by qh_initqhull_buffers */
qh_memfree(qh NEARzero, qh hull_dim * sizeof(realT));
qh_memfree(qh lower_threshold, (qh input_dim+1) * sizeof(realT));
qh_memfree(qh upper_threshold, (qh input_dim+1) * sizeof(realT));
qh_memfree(qh lower_bound, (qh input_dim+1) * sizeof(realT));
qh_memfree(qh upper_bound, (qh input_dim+1) * sizeof(realT));
qh_memfree(qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
qh_memfree(qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
qh lower_bound= qh upper_bound= NULL;
qh gm_matrix= NULL;
qh gm_row= NULL;
qh_setfree(&qh other_points);
qh_setfree(&qh del_vertices);
qh_setfree(&qh coplanarfacetset);
if (qh line) /* allocated by qh_readinput, freed if no error */
qh_free(qh line);
if (qh half_space)
qh_free(qh half_space);
if (qh temp_malloc)
qh_free(qh temp_malloc);
if (qh feasible_point) /* allocated by qh_readfeasible */
qh_free(qh feasible_point);
if (qh feasible_string) /* allocated by qh_initflags */
qh_free(qh feasible_string);
qh line= qh feasible_string= NULL;
qh half_space= qh feasible_point= qh temp_malloc= NULL;
/* usually allocated by qh_readinput */
if (qh first_point && qh POINTSmalloc) {
qh_free(qh first_point);
qh first_point= NULL;
}
if (qh input_points && qh input_malloc) { /* set by qh_joggleinput */
qh_free(qh input_points);
qh input_points= NULL;
}
trace5((qh ferr, 5002, "qh_freebuffers: finished\n"));
} /* freebuffers */
/*---------------------------------
qh_freebuild( allmem )
free global memory used by qh_initbuild and qh_buildhull
if !allmem,
does not free short memory (e.g., facetT, freed by qh_memfreeshort)
design:
free centrums
free each vertex
mark unattached ridges
for each facet
free ridges
free outside set, coplanar set, neighbor set, ridge set, vertex set
free facet
free hash table
free interior point
free merge set
free temporary sets
*/
void qh_freebuild(boolT allmem) {
facetT *facet;
vertexT *vertex;
ridgeT *ridge, **ridgep;
mergeT *merge, **mergep;
trace1((qh ferr, 1005, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
if (qh del_vertices)
qh_settruncate(qh del_vertices, 0);
if (allmem) {
while ((vertex= qh vertex_list)) {
if (vertex->next)
qh_delvertex(vertex);
else {
qh_memfree(vertex, (int)sizeof(vertexT));
qh newvertex_list= qh vertex_list= NULL;
}
}
}else if (qh VERTEXneighbors) {
FORALLvertices
qh_setfreelong(&(vertex->neighbors));
}
qh VERTEXneighbors= False;
qh GOODclosest= NULL;
if (allmem) {
FORALLfacets {
FOREACHridge_(facet->ridges)
ridge->seen= False;
}
FORALLfacets {
if (facet->visible) {
FOREACHridge_(facet->ridges) {
if (!otherfacet_(ridge, facet)->visible)
ridge->seen= True; /* an unattached ridge */
}
}
}
while ((facet= qh facet_list)) {
FOREACHridge_(facet->ridges) {
if (ridge->seen) {
qh_setfree(&(ridge->vertices));
qh_memfree(ridge, (int)sizeof(ridgeT));
}else
ridge->seen= True;
}
qh_setfree(&(facet->outsideset));
qh_setfree(&(facet->coplanarset));
qh_setfree(&(facet->neighbors));
qh_setfree(&(facet->ridges));
qh_setfree(&(facet->vertices));
if (facet->next)
qh_delfacet(facet);
else {
qh_memfree(facet, (int)sizeof(facetT));
qh visible_list= qh newfacet_list= qh facet_list= NULL;
}
}
}else {
FORALLfacets {
qh_setfreelong(&(facet->outsideset));
qh_setfreelong(&(facet->coplanarset));
if (!facet->simplicial) {
qh_setfreelong(&(facet->neighbors));
qh_setfreelong(&(facet->ridges));
qh_setfreelong(&(facet->vertices));
}
}
}
qh_setfree(&(qh hash_table));
qh_memfree(qh interior_point, qh normal_size);
qh interior_point= NULL;
FOREACHmerge_(qh facet_mergeset) /* usually empty */
qh_memfree(merge, (int)sizeof(mergeT));
qh facet_mergeset= NULL; /* temp set */
qh degen_mergeset= NULL; /* temp set */
qh_settempfree_all();
} /* freebuild */
/*---------------------------------
qh_freeqhull( allmem )
see qh_freeqhull2
if qh_QHpointer, frees qh_qh
*/
void qh_freeqhull(boolT allmem) {
qh_freeqhull2(allmem);
#if qh_QHpointer
qh_free(qh_qh);
qh_qh= NULL;
#endif
}
/*---------------------------------
qh_freeqhull2( allmem )
free global memory
if !allmem,
does not free short memory (freed by qh_memfreeshort)
notes:
sets qh.NOerrexit in case caller forgets to
see:
see qh_initqhull_start2()
design:
free global and temporary memory from qh_initbuild and qh_buildhull
free buffers
free statistics
*/
void qh_freeqhull2(boolT allmem) {
trace1((qh ferr, 1006, "qh_freeqhull2: free global memory\n"));
qh NOerrexit= True; /* no more setjmp since called at exit and ~QhullQh */
qh_freebuild(allmem);
qh_freebuffers();
qh_freestatistics();
#if qh_QHpointer
memset((char *)qh_qh, 0, sizeof(qhT));
/* qh_qh freed by caller, qh_freeqhull() */
#else
memset((char *)&qh_qh, 0, sizeof(qhT));
#endif
qh NOerrexit= True;
} /* freeqhull2 */
/*---------------------------------
qh_init_A( infile, outfile, errfile, argc, argv )
initialize memory and stdio files
convert input options to option string (qh.qhull_command)
notes:
infile may be NULL if qh_readpoints() is not called
errfile should always be defined. It is used for reporting
errors. outfile is used for output and format options.
argc/argv may be 0/NULL
called before error handling initialized
qh_errexit() may not be used
*/
void qh_init_A(FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
qh_meminit(errfile);
qh_initqhull_start(infile, outfile, errfile);
qh_init_qhull_command(argc, argv);
} /* init_A */
/*---------------------------------
qh_init_B( points, numpoints, dim, ismalloc )
initialize globals for points array
points has numpoints dim-dimensional points
points[0] is the first coordinate of the first point
points[1] is the second coordinate of the first point
points[dim] is the first coordinate of the second point
ismalloc=True
Qhull will call qh_free(points) on exit or input transformation
ismalloc=False
Qhull will allocate a new point array if needed for input transformation
qh.qhull_command
is the option string.
It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
returns:
if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
projects the input to a new point array
if qh.DELAUNAY,
qh.hull_dim is increased by one
if qh.ATinfinity,
qh_projectinput adds point-at-infinity for Delaunay tri.
if qh.SCALEinput
changes the upper and lower bounds of the input, see qh_scaleinput()
if qh.ROTATEinput
rotates the input by a random rotation, see qh_rotateinput()
if qh.DELAUNAY
rotates about the last coordinate
notes:
called after points are defined
qh_errexit() may be used
*/
void qh_init_B(coordT *points, int numpoints, int dim, boolT ismalloc) {
qh_initqhull_globals(points, numpoints, dim, ismalloc);
if (qhmem.LASTsize == 0)
qh_initqhull_mem();
/* mem.c and qset.c are initialized */
qh_initqhull_buffers();
qh_initthresholds(qh qhull_command);
if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay))
qh_projectinput();
if (qh SCALEinput)
qh_scaleinput();
if (qh ROTATErandom >= 0) {
qh_randommatrix(qh gm_matrix, qh hull_dim, qh gm_row);
if (qh DELAUNAY) {
int k, lastk= qh hull_dim-1;
for (k=0; k < lastk; k++) {
qh gm_row[k][lastk]= 0.0;
qh gm_row[lastk][k]= 0.0;
}
qh gm_row[lastk][lastk]= 1.0;
}
qh_gram_schmidt(qh hull_dim, qh gm_row);
qh_rotateinput(qh gm_row);
}
} /* init_B */
/*---------------------------------
qh_init_qhull_command( argc, argv )
build qh.qhull_command from argc/argv
returns:
a space-delimited string of options (just as typed)
notes:
makes option string easy to input and output
argc/argv may be 0/NULL
*/
void qh_init_qhull_command(int argc, char *argv[]) {
if (!qh_argv_to_command(argc, argv, qh qhull_command, (int)sizeof(qh qhull_command))){
/* Assumes qh.ferr is defined. */
qh_fprintf(qh ferr, 6033, "qhull input error: more than %d characters in command line\n",
(int)sizeof(qh qhull_command));
qh_exit(qh_ERRinput); /* error reported, can not use qh_errexit */
}
} /* init_qhull_command */
/*---------------------------------
qh_initflags( commandStr )
set flags and initialized constants from commandStr
returns:
sets qh.qhull_command to command if needed
notes:
ignores first word (e.g., "qhull d")
use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
see:
qh_initthresholds() continues processing of 'Pdn' and 'PDn'
'prompt' in unix.c for documentation
design:
for each space-deliminated option group
if top-level option
check syntax
append approriate option to option string
set appropriate global variable or append printFormat to print options
else
for each sub-option
check syntax
append approriate option to option string
set appropriate global variable or append printFormat to print options
*/
void qh_initflags(char *command) {
int k, i, lastproject;
char *s= command, *t, *prev_s, *start, key;
boolT isgeom= False, wasproject;
realT r;
if (command <= &qh qhull_command[0] || command > &qh qhull_command[0] + sizeof(qh qhull_command)) {
if (command != &qh qhull_command[0]) {
*qh qhull_command= '\0';
strncat(qh qhull_command, command, sizeof(qh qhull_command)-strlen(qh qhull_command)-1);
}
while (*s && !isspace(*s)) /* skip program name */
s++;
}
while (*s) {
while (*s && isspace(*s))
s++;
if (*s == '-')
s++;
if (!*s)
break;
prev_s= s;
switch (*s++) {
case 'd':
qh_option("delaunay", NULL, NULL);
qh DELAUNAY= True;
break;
case 'f':
qh_option("facets", NULL, NULL);
qh_appendprint(qh_PRINTfacets);
break;
case 'i':
qh_option("incidence", NULL, NULL);
qh_appendprint(qh_PRINTincidences);
break;
case 'm':
qh_option("mathematica", NULL, NULL);
qh_appendprint(qh_PRINTmathematica);
break;
case 'n':
qh_option("normals", NULL, NULL);
qh_appendprint(qh_PRINTnormals);
break;
case 'o':
qh_option("offFile", NULL, NULL);
qh_appendprint(qh_PRINToff);
break;
case 'p':
qh_option("points", NULL, NULL);
qh_appendprint(qh_PRINTpoints);
break;
case 's':
qh_option("summary", NULL, NULL);
qh PRINTsummary= True;
break;
case 'v':
qh_option("voronoi", NULL, NULL);
qh VORONOI= True;
qh DELAUNAY= True;
break;
case 'A':
if (!isdigit(*s) && *s != '.' && *s != '-')
qh_fprintf(qh ferr, 7002, "qhull warning: no maximum cosine angle given for option 'An'. Ignored.\n");
else {
if (*s == '-') {
qh premerge_cos= -qh_strtod(s, &s);
qh_option("Angle-premerge-", NULL, &qh premerge_cos);
qh PREmerge= True;
}else {
qh postmerge_cos= qh_strtod(s, &s);
qh_option("Angle-postmerge", NULL, &qh postmerge_cos);
qh POSTmerge= True;
}
qh MERGING= True;
}
break;
case 'C':
if (!isdigit(*s) && *s != '.' && *s != '-')
qh_fprintf(qh ferr, 7003, "qhull warning: no centrum radius given for option 'Cn'. Ignored.\n");
else {
if (*s == '-') {
qh premerge_centrum= -qh_strtod(s, &s);
qh_option("Centrum-premerge-", NULL, &qh premerge_centrum);
qh PREmerge= True;
}else {
qh postmerge_centrum= qh_strtod(s, &s);
qh_option("Centrum-postmerge", NULL, &qh postmerge_centrum);
qh POSTmerge= True;
}
qh MERGING= True;
}
break;
case 'E':
if (*s == '-')
qh_fprintf(qh ferr, 7004, "qhull warning: negative maximum roundoff given for option 'An'. Ignored.\n");
else if (!isdigit(*s))
qh_fprintf(qh ferr, 7005, "qhull warning: no maximum roundoff given for option 'En'. Ignored.\n");
else {
qh DISTround= qh_strtod(s, &s);
qh_option("Distance-roundoff", NULL, &qh DISTround);
qh SETroundoff= True;
}
break;
case 'H':
start= s;
qh HALFspace= True;
qh_strtod(s, &t);
while (t > s) {
if (*t && !isspace(*t)) {
if (*t == ',')
t++;
else
qh_fprintf(qh ferr, 7006, "qhull warning: origin for Halfspace intersection should be 'Hn,n,n,...'\n");
}
s= t;
qh_strtod(s, &t);
}
if (start < t) {
if (!(qh feasible_string= (char*)calloc((size_t)(t-start+1), (size_t)1))) {
qh_fprintf(qh ferr, 6034, "qhull error: insufficient memory for 'Hn,n,n'\n");
qh_errexit(qh_ERRmem, NULL, NULL);
}
strncpy(qh feasible_string, start, (size_t)(t-start));
qh_option("Halfspace-about", NULL, NULL);
qh_option(qh feasible_string, NULL, NULL);
}else
qh_option("Halfspace", NULL, NULL);
break;
case 'R':
if (!isdigit(*s))
qh_fprintf(qh ferr, 7007, "qhull warning: missing random perturbation for option 'Rn'. Ignored\n");
else {
qh RANDOMfactor= qh_strtod(s, &s);
qh_option("Random_perturb", NULL, &qh RANDOMfactor);
qh RANDOMdist= True;
}
break;
case 'V':
if (!isdigit(*s) && *s != '-')
qh_fprintf(qh ferr, 7008, "qhull warning: missing visible distance for option 'Vn'. Ignored\n");
else {
qh MINvisible= qh_strtod(s, &s);
qh_option("Visible", NULL, &qh MINvisible);
}
break;
case 'U':
if (!isdigit(*s) && *s != '-')
qh_fprintf(qh ferr, 7009, "qhull warning: missing coplanar distance for option 'Un'. Ignored\n");
else {
qh MAXcoplanar= qh_strtod(s, &s);
qh_option("U-coplanar", NULL, &qh MAXcoplanar);
}
break;
case 'W':
if (*s == '-')
qh_fprintf(qh ferr, 7010, "qhull warning: negative outside width for option 'Wn'. Ignored.\n");
else if (!isdigit(*s))
qh_fprintf(qh ferr, 7011, "qhull warning: missing outside width for option 'Wn'. Ignored\n");
else {
qh MINoutside= qh_strtod(s, &s);
qh_option("W-outside", NULL, &qh MINoutside);
qh APPROXhull= True;
}
break;
/************ sub menus ***************/
case 'F':
while (*s && !isspace(*s)) {
switch (*s++) {
case 'a':
qh_option("Farea", NULL, NULL);
qh_appendprint(qh_PRINTarea);
qh GETarea= True;
break;
case 'A':
qh_option("FArea-total", NULL, NULL);
qh GETarea= True;
break;
case 'c':
qh_option("Fcoplanars", NULL, NULL);
qh_appendprint(qh_PRINTcoplanars);
break;
case 'C':
qh_option("FCentrums", NULL, NULL);
qh_appendprint(qh_PRINTcentrums);
break;
case 'd':
qh_option("Fd-cdd-in", NULL, NULL);
qh CDDinput= True;
break;
case 'D':
qh_option("FD-cdd-out", NULL, NULL);
qh CDDoutput= True;
break;
case 'F':
qh_option("FFacets-xridge", NULL, NULL);
qh_appendprint(qh_PRINTfacets_xridge);
break;
case 'i':
qh_option("Finner", NULL, NULL);
qh_appendprint(qh_PRINTinner);
break;
case 'I':
qh_option("FIDs", NULL, NULL);
qh_appendprint(qh_PRINTids);
break;
case 'm':
qh_option("Fmerges", NULL, NULL);
qh_appendprint(qh_PRINTmerges);
break;
case 'M':
qh_option("FMaple", NULL, NULL);
qh_appendprint(qh_PRINTmaple);
break;
case 'n':
qh_option("Fneighbors", NULL, NULL);
qh_appendprint(qh_PRINTneighbors);
break;
case 'N':
qh_option("FNeighbors-vertex", NULL, NULL);
qh_appendprint(qh_PRINTvneighbors);
break;
case 'o':
qh_option("Fouter", NULL, NULL);
qh_appendprint(qh_PRINTouter);
break;
case 'O':
if (qh PRINToptions1st) {
qh_option("FOptions", NULL, NULL);
qh_appendprint(qh_PRINToptions);
}else
qh PRINToptions1st= True;
break;
case 'p':
qh_option("Fpoint-intersect", NULL, NULL);
qh_appendprint(qh_PRINTpointintersect);
break;
case 'P':
qh_option("FPoint-nearest", NULL, NULL);
qh_appendprint(qh_PRINTpointnearest);
break;
case 'Q':
qh_option("FQhull", NULL, NULL);
qh_appendprint(qh_PRINTqhull);
break;
case 's':
qh_option("Fsummary", NULL, NULL);
qh_appendprint(qh_PRINTsummary);
break;
case 'S':
qh_option("FSize", NULL, NULL);
qh_appendprint(qh_PRINTsize);
qh GETarea= True;
break;
case 't':
qh_option("Ftriangles", NULL, NULL);
qh_appendprint(qh_PRINTtriangles);
break;
case 'v':
/* option set in qh_initqhull_globals */
qh_appendprint(qh_PRINTvertices);
break;
case 'V':
qh_option("FVertex-average", NULL, NULL);
qh_appendprint(qh_PRINTaverage);
break;
case 'x':
qh_option("Fxtremes", NULL, NULL);
qh_appendprint(qh_PRINTextremes);
break;
default:
s--;
qh_fprintf(qh ferr, 7012, "qhull warning: unknown 'F' output option %c, rest ignored\n", (int)s[0]);
while (*++s && !isspace(*s));
break;
}
}
break;
case 'G':
isgeom= True;
qh_appendprint(qh_PRINTgeom);
while (*s && !isspace(*s)) {
switch (*s++) {
case 'a':
qh_option("Gall-points", NULL, NULL);
qh PRINTdots= True;
break;
case 'c':
qh_option("Gcentrums", NULL, NULL);
qh PRINTcentrums= True;
break;
case 'h':
qh_option("Gintersections", NULL, NULL);
qh DOintersections= True;
break;
case 'i':
qh_option("Ginner", NULL, NULL);
qh PRINTinner= True;
break;
case 'n':
qh_option("Gno-planes", NULL, NULL);
qh PRINTnoplanes= True;
break;
case 'o':
qh_option("Gouter", NULL, NULL);
qh PRINTouter= True;
break;
case 'p':
qh_option("Gpoints", NULL, NULL);
qh PRINTcoplanar= True;
break;
case 'r':
qh_option("Gridges", NULL, NULL);
qh PRINTridges= True;
break;
case 't':
qh_option("Gtransparent", NULL, NULL);
qh PRINTtransparent= True;
break;
case 'v':
qh_option("Gvertices", NULL, NULL);
qh PRINTspheres= True;
break;
case 'D':
if (!isdigit(*s))
qh_fprintf(qh ferr, 6035, "qhull input error: missing dimension for option 'GDn'\n");
else {
if (qh DROPdim >= 0)
qh_fprintf(qh ferr, 7013, "qhull warning: can only drop one dimension. Previous 'GD%d' ignored\n",
qh DROPdim);
qh DROPdim= qh_strtol(s, &s);
qh_option("GDrop-dim", &qh DROPdim, NULL);
}
break;
default:
s--;
qh_fprintf(qh ferr, 7014, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
while (*++s && !isspace(*s));
break;
}
}
break;
case 'P':
while (*s && !isspace(*s)) {
switch (*s++) {
case 'd': case 'D': /* see qh_initthresholds() */
key= s[-1];
i= qh_strtol(s, &s);
r= 0;
if (*s == ':') {
s++;
r= qh_strtod(s, &s);
}
if (key == 'd')
qh_option("Pdrop-facets-dim-less", &i, &r);
else
qh_option("PDrop-facets-dim-more", &i, &r);
break;
case 'g':
qh_option("Pgood-facets", NULL, NULL);
qh PRINTgood= True;
break;
case 'G':
qh_option("PGood-facet-neighbors", NULL, NULL);
qh PRINTneighbors= True;
break;
case 'o':
qh_option("Poutput-forced", NULL, NULL);
qh FORCEoutput= True;
break;
case 'p':
qh_option("Pprecision-ignore", NULL, NULL);
qh PRINTprecision= False;
break;
case 'A':
if (!isdigit(*s))
qh_fprintf(qh ferr, 6036, "qhull input error: missing facet count for keep area option 'PAn'\n");
else {
qh KEEParea= qh_strtol(s, &s);
qh_option("PArea-keep", &qh KEEParea, NULL);
qh GETarea= True;
}
break;
case 'F':
if (!isdigit(*s))
qh_fprintf(qh ferr, 6037, "qhull input error: missing facet area for option 'PFn'\n");
else {
qh KEEPminArea= qh_strtod(s, &s);
qh_option("PFacet-area-keep", NULL, &qh KEEPminArea);
qh GETarea= True;
}
break;
case 'M':
if (!isdigit(*s))
qh_fprintf(qh ferr, 6038, "qhull input error: missing merge count for option 'PMn'\n");
else {
qh KEEPmerge= qh_strtol(s, &s);
qh_option("PMerge-keep", &qh KEEPmerge, NULL);
}
break;
default:
s--;
qh_fprintf(qh ferr, 7015, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[0]);
while (*++s && !isspace(*s));
break;
}
}
break;
case 'Q':
lastproject= -1;
while (*s && !isspace(*s)) {
switch (*s++) {
case 'b': case 'B': /* handled by qh_initthresholds */
key= s[-1];
if (key == 'b' && *s == 'B') {
s++;
r= qh_DEFAULTbox;
qh SCALEinput= True;
qh_option("QbBound-unit-box", NULL, &r);
break;
}
if (key == 'b' && *s == 'b') {
s++;
qh SCALElast= True;
qh_option("Qbbound-last", NULL, NULL);
break;
}
k= qh_strtol(s, &s);
r= 0.0;
wasproject= False;
if (*s == ':') {
s++;
if ((r= qh_strtod(s, &s)) == 0.0) {
t= s; /* need true dimension for memory allocation */
while (*t && !isspace(*t)) {
if (toupper(*t++) == 'B'
&& k == qh_strtol(t, &t)
&& *t++ == ':'
&& qh_strtod(t, &t) == 0.0) {
qh PROJECTinput++;
trace2((qh ferr, 2004, "qh_initflags: project dimension %d\n", k));
qh_option("Qb-project-dim", &k, NULL);
wasproject= True;
lastproject= k;
break;
}
}
}
}
if (!wasproject) {
if (lastproject == k && r == 0.0)
lastproject= -1; /* doesn't catch all possible sequences */
else if (key == 'b') {
qh SCALEinput= True;
if (r == 0.0)
r= -qh_DEFAULTbox;
qh_option("Qbound-dim-low", &k, &r);
}else {
qh SCALEinput= True;
if (r == 0.0)
r= qh_DEFAULTbox;
qh_option("QBound-dim-high", &k, &r);
}
}
break;
case 'c':
qh_option("Qcoplanar-keep", NULL, NULL);
qh KEEPcoplanar= True;
break;
case 'f':
qh_option("Qfurthest-outside", NULL, NULL);
qh BESToutside= True;
break;
case 'g':
qh_option("Qgood-facets-only", NULL, NULL);
qh ONLYgood= True;
break;
case 'i':
qh_option("Qinterior-keep", NULL, NULL);
qh KEEPinside= True;
break;
case 'm':
qh_option("Qmax-outside-only", NULL, NULL);
qh ONLYmax= True;
break;
case 'r':
qh_option("Qrandom-outside", NULL, NULL);
qh RANDOMoutside= True;
break;
case 's':
qh_option("Qsearch-initial-simplex", NULL, NULL);
qh ALLpoints= True;
break;
case 't':
qh_option("Qtriangulate", NULL, NULL);
qh TRIangulate= True;
break;
case 'T':
qh_option("QTestPoints", NULL, NULL);
if (!isdigit(*s))
qh_fprintf(qh ferr, 6039, "qhull input error: missing number of test points for option 'QTn'\n");
else {
qh TESTpoints= qh_strtol(s, &s);
qh_option("QTestPoints", &qh TESTpoints, NULL);
}
break;
case 'u':
qh_option("QupperDelaunay", NULL, NULL);
qh UPPERdelaunay= True;
break;
case 'v':
qh_option("Qvertex-neighbors-convex", NULL, NULL);
qh TESTvneighbors= True;
break;
case 'x':
qh_option("Qxact-merge", NULL, NULL);
qh MERGEexact= True;
break;
case 'z':
qh_option("Qz-infinity-point", NULL, NULL);
qh ATinfinity= True;
break;
case '0':
qh_option("Q0-no-premerge", NULL, NULL);
qh NOpremerge= True;
break;
case '1':
if (!isdigit(*s)) {
qh_option("Q1-no-angle-sort", NULL, NULL);
qh ANGLEmerge= False;
break;
}
switch (*s++) {
case '0':
qh_option("Q10-no-narrow", NULL, NULL);
qh NOnarrow= True;
break;
case '1':
qh_option("Q11-trinormals Qtriangulate", NULL, NULL);
qh TRInormals= True;
qh TRIangulate= True;
break;
default:
s--;
qh_fprintf(qh ferr, 7016, "qhull warning: unknown 'Q' qhull option 1%c, rest ignored\n", (int)s[0]);
while (*++s && !isspace(*s));
break;
}
break;
case '2':
qh_option("Q2-no-merge-independent", NULL, NULL);
qh MERGEindependent= False;
goto LABELcheckdigit;
break; /* no warnings */
case '3':
qh_option("Q3-no-merge-vertices", NULL, NULL);
qh MERGEvertices= False;
LABELcheckdigit:
if (isdigit(*s))
qh_fprintf(qh ferr, 7017, "qhull warning: can not follow '1', '2', or '3' with a digit. '%c' skipped.\n",
*s++);
break;
case '4':
qh_option("Q4-avoid-old-into-new", NULL, NULL);
qh AVOIDold= True;
break;
case '5':
qh_option("Q5-no-check-outer", NULL, NULL);
qh SKIPcheckmax= True;
break;
case '6':
qh_option("Q6-no-concave-merge", NULL, NULL);
qh SKIPconvex= True;
break;
case '7':
qh_option("Q7-no-breadth-first", NULL, NULL);
qh VIRTUALmemory= True;
break;
case '8':
qh_option("Q8-no-near-inside", NULL, NULL);
qh NOnearinside= True;
break;
case '9':
qh_option("Q9-pick-furthest", NULL, NULL);
qh PICKfurthest= True;
break;
case 'G':
i= qh_strtol(s, &t);
if (qh GOODpoint)
qh_fprintf(qh ferr, 7018, "qhull warning: good point already defined for option 'QGn'. Ignored\n");
else if (s == t)
qh_fprintf(qh ferr, 7019, "qhull warning: missing good point id for option 'QGn'. Ignored\n");
else if (i < 0 || *s == '-') {
qh GOODpoint= i-1;
qh_option("QGood-if-dont-see-point", &i, NULL);
}else {
qh GOODpoint= i+1;
qh_option("QGood-if-see-point", &i, NULL);
}
s= t;
break;
case 'J':
if (!isdigit(*s) && *s != '-')
qh JOGGLEmax= 0.0;
else {
qh JOGGLEmax= (realT) qh_strtod(s, &s);
qh_option("QJoggle", NULL, &qh JOGGLEmax);
}
break;
case 'R':
if (!isdigit(*s) && *s != '-')
qh_fprintf(qh ferr, 7020, "qhull warning: missing random seed for option 'QRn'. Ignored\n");
else {
qh ROTATErandom= i= qh_strtol(s, &s);
if (i > 0)
qh_option("QRotate-id", &i, NULL );
else if (i < -1)
qh_option("QRandom-seed", &i, NULL );
}
break;
case 'V':
i= qh_strtol(s, &t);
if (qh GOODvertex)
qh_fprintf(qh ferr, 7021, "qhull warning: good vertex already defined for option 'QVn'. Ignored\n");
else if (s == t)
qh_fprintf(qh ferr, 7022, "qhull warning: no good point id given for option 'QVn'. Ignored\n");
else if (i < 0) {
qh GOODvertex= i - 1;
qh_option("QV-good-facets-not-point", &i, NULL);
}else {
qh_option("QV-good-facets-point", &i, NULL);
qh GOODvertex= i + 1;
}
s= t;
break;
default:
s--;
qh_fprintf(qh ferr, 7023, "qhull warning: unknown 'Q' qhull option %c, rest ignored\n", (int)s[0]);
while (*++s && !isspace(*s));
break;
}
}
break;
case 'T':
while (*s && !isspace(*s)) {
if (isdigit(*s) || *s == '-')
qh IStracing= qh_strtol(s, &s);
else switch (*s++) {
case 'a':
qh_option("Tannotate-output", NULL, NULL);
qh ANNOTATEoutput= True;
break;
case 'c':
qh_option("Tcheck-frequently", NULL, NULL);
qh CHECKfrequently= True;
break;
case 's':
qh_option("Tstatistics", NULL, NULL);
qh PRINTstatistics= True;
break;
case 'v':
qh_option("Tverify", NULL, NULL);
qh VERIFYoutput= True;
break;
case 'z':
if (qh ferr == qh_FILEstderr) {
/* The C++ interface captures the output in qh_fprint_qhull() */
qh_option("Tz-stdout", NULL, NULL);
qh USEstdout= True;
}else if (!qh fout)
qh_fprintf(qh ferr, 7024, "qhull warning: output file undefined(stdout). Option 'Tz' ignored.\n");
else {
qh_option("Tz-stdout", NULL, NULL);
qh USEstdout= True;
qh ferr= qh fout;
qhmem.ferr= qh fout;
}
break;
case 'C':
if (!isdigit(*s))
qh_fprintf(qh ferr, 7025, "qhull warning: missing point id for cone for trace option 'TCn'. Ignored\n");
else {
i= qh_strtol(s, &s);
qh_option("TCone-stop", &i, NULL);
qh STOPcone= i + 1;
}
break;
case 'F':
if (!isdigit(*s))
qh_fprintf(qh ferr, 7026, "qhull warning: missing frequency count for trace option 'TFn'. Ignored\n");
else {
qh REPORTfreq= qh_strtol(s, &s);
qh_option("TFacet-log", &qh REPORTfreq, NULL);
qh REPORTfreq2= qh REPORTfreq/2; /* for tracemerging() */
}
break;
case 'I':
if (!isspace(*s))
qh_fprintf(qh ferr, 7027, "qhull warning: missing space between 'TI' and filename, %s\n", s);
while (isspace(*s))
s++;
t= qh_skipfilename(s);
{
char filename[qh_FILENAMElen];
qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s)); /* WARN64 */
s= t;
if (!freopen(filename, "r", stdin)) {
qh_fprintf(qh ferr, 6041, "qhull error: could not open file \"%s\".", filename);
qh_errexit(qh_ERRinput, NULL, NULL);
}else {
qh_option("TInput-file", NULL, NULL);
qh_option(filename, NULL, NULL);
}
}
break;
case 'O':
if (!isspace(*s))
qh_fprintf(qh ferr, 7028, "qhull warning: missing space between 'TO' and filename, %s\n", s);
while (isspace(*s))
s++;
t= qh_skipfilename(s);
{
char filename[qh_FILENAMElen];
qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s)); /* WARN64 */
s= t;
if (!freopen(filename, "w", stdout)) {
qh_fprintf(qh ferr, 6044, "qhull error: could not open file \"%s\".", filename);
qh_errexit(qh_ERRinput, NULL, NULL);
}else {
qh_option("TOutput-file", NULL, NULL);
qh_option(filename, NULL, NULL);
}
}
break;
case 'P':
if (!isdigit(*s))
qh_fprintf(qh ferr, 7029, "qhull warning: missing point id for trace option 'TPn'. Ignored\n");
else {
qh TRACEpoint= qh_strtol(s, &s);
qh_option("Trace-point", &qh TRACEpoint, NULL);
}
break;
case 'M':
if (!isdigit(*s))
qh_fprintf(qh ferr, 7030, "qhull warning: missing merge id for trace option 'TMn'. Ignored\n");
else {
qh TRACEmerge= qh_strtol(s, &s);
qh_option("Trace-merge", &qh TRACEmerge, NULL);
}
break;
case 'R':
if (!isdigit(*s))
qh_fprintf(qh ferr, 7031, "qhull warning: missing rerun count for trace option 'TRn'. Ignored\n");
else {
qh RERUN= qh_strtol(s, &s);
qh_option("TRerun", &qh RERUN, NULL);
}
break;
case 'V':
i= qh_strtol(s, &t);
if (s == t)
qh_fprintf(qh ferr, 7032, "qhull warning: missing furthest point id for trace option 'TVn'. Ignored\n");
else if (i < 0) {
qh STOPpoint= i - 1;
qh_option("TV-stop-before-point", &i, NULL);
}else {
qh STOPpoint= i + 1;
qh_option("TV-stop-after-point", &i, NULL);
}
s= t;
break;
case 'W':
if (!isdigit(*s))
qh_fprintf(qh ferr, 7033, "qhull warning: missing max width for trace option 'TWn'. Ignored\n");
else {
qh TRACEdist= (realT) qh_strtod(s, &s);
qh_option("TWide-trace", NULL, &qh TRACEdist);
}
break;
default:
s--;
qh_fprintf(qh ferr, 7034, "qhull warning: unknown 'T' trace option %c, rest ignored\n", (int)s[0]);
while (*++s && !isspace(*s));
break;
}
}
break;
default:
qh_fprintf(qh ferr, 7035, "qhull warning: unknown flag %c(%x)\n", (int)s[-1],
(int)s[-1]);
break;
}
if (s-1 == prev_s && *s && !isspace(*s)) {
qh_fprintf(qh ferr, 7036, "qhull warning: missing space after flag %c(%x); reserved for menu. Skipped.\n",
(int)*prev_s, (int)*prev_s);
while (*s && !isspace(*s))
s++;
}
}
if (qh STOPcone && qh JOGGLEmax < REALmax/2)
qh_fprintf(qh ferr, 7078, "qhull warning: 'TCn' (stopCone) ignored when used with 'QJn' (joggle)\n");
if (isgeom && !qh FORCEoutput && qh PRINTout[1])
qh_fprintf(qh ferr, 7037, "qhull warning: additional output formats are not compatible with Geomview\n");
/* set derived values in qh_initqhull_globals */
} /* initflags */
/*---------------------------------
qh_initqhull_buffers()
initialize global memory buffers
notes:
must match qh_freebuffers()
*/
void qh_initqhull_buffers(void) {
int k;
qh TEMPsize= (qhmem.LASTsize - sizeof(setT))/SETelemsize;
if (qh TEMPsize <= 0 || qh TEMPsize > qhmem.LASTsize)
qh TEMPsize= 8; /* e.g., if qh_NOmem */
qh other_points= qh_setnew(qh TEMPsize);
qh del_vertices= qh_setnew(qh TEMPsize);
qh coplanarfacetset= qh_setnew(qh TEMPsize);
qh NEARzero= (realT *)qh_memalloc(qh hull_dim * sizeof(realT));
qh lower_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
qh upper_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
qh lower_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
qh upper_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
for (k=qh input_dim+1; k--; ) { /* duplicated in qh_initqhull_buffers and qh_clear_ouputflags */
qh lower_threshold[k]= -REALmax;
qh upper_threshold[k]= REALmax;
qh lower_bound[k]= -REALmax;
qh upper_bound[k]= REALmax;
}
qh gm_matrix= (coordT *)qh_memalloc((qh hull_dim+1) * qh hull_dim * sizeof(coordT));
qh gm_row= (coordT **)qh_memalloc((qh hull_dim+1) * sizeof(coordT *));
} /* initqhull_buffers */
/*---------------------------------
qh_initqhull_globals( points, numpoints, dim, ismalloc )
initialize globals
if ismalloc
points were malloc'd and qhull should free at end
returns:
sets qh.first_point, num_points, input_dim, hull_dim and others
seeds random number generator (seed=1 if tracing)
modifies qh.hull_dim if ((qh.DELAUNAY and qh.PROJECTdelaunay) or qh.PROJECTinput)
adjust user flags as needed
also checks DIM3 dependencies and constants
notes:
do not use qh_point() since an input transformation may move them elsewhere
see:
qh_initqhull_start() sets default values for non-zero globals
design:
initialize points array from input arguments
test for qh.ZEROcentrum
(i.e., use opposite vertex instead of cetrum for convexity testing)
initialize qh.CENTERtype, qh.normal_size,
qh.center_size, qh.TRACEpoint/level,
initialize and test random numbers
qh_initqhull_outputflags() -- adjust and test output flags
*/
void qh_initqhull_globals(coordT *points, int numpoints, int dim, boolT ismalloc) {
int seed, pointsneeded, extra= 0, i, randi, k;
realT randr;
realT factorial;
time_t timedata;
trace0((qh ferr, 13, "qh_initqhull_globals: for %s | %s\n", qh rbox_command,
qh qhull_command));
qh POINTSmalloc= ismalloc;
qh first_point= points;
qh num_points= numpoints;
qh hull_dim= qh input_dim= dim;
if (!qh NOpremerge && !qh MERGEexact && !qh PREmerge && qh JOGGLEmax > REALmax/2) {
qh MERGING= True;
if (qh hull_dim <= 4) {
qh PREmerge= True;
qh_option("_pre-merge", NULL, NULL);
}else {
qh MERGEexact= True;
qh_option("Qxact_merge", NULL, NULL);
}
}else if (qh MERGEexact)
qh MERGING= True;
if (!qh NOpremerge && qh JOGGLEmax > REALmax/2) {
#ifdef qh_NOmerge
qh JOGGLEmax= 0.0;
#endif
}
if (qh TRIangulate && qh JOGGLEmax < REALmax/2 && qh PRINTprecision)
qh_fprintf(qh ferr, 7038, "qhull warning: joggle('QJ') always produces simplicial output. Triangulated output('Qt') does nothing.\n");
if (qh JOGGLEmax < REALmax/2 && qh DELAUNAY && !qh SCALEinput && !qh SCALElast) {
qh SCALElast= True;
qh_option("Qbbound-last-qj", NULL, NULL);
}
if (qh MERGING && !qh POSTmerge && qh premerge_cos > REALmax/2
&& qh premerge_centrum == 0) {
qh ZEROcentrum= True;
qh ZEROall_ok= True;
qh_option("_zero-centrum", NULL, NULL);
}
if (qh JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh PRINTprecision)
qh_fprintf(qh ferr, 7039, "qhull warning: real epsilon, %2.2g, is probably too large for joggle('QJn')\nRecompile with double precision reals(see user.h).\n",
REALepsilon);
#ifdef qh_NOmerge
if (qh MERGING) {
qh_fprintf(qh ferr, 6045, "qhull input error: merging not installed(qh_NOmerge + 'Qx', 'Cn' or 'An')\n");
qh_errexit(qh_ERRinput, NULL, NULL);
}
#endif
if (qh DELAUNAY && qh KEEPcoplanar && !qh KEEPinside) {
qh KEEPinside= True;
qh_option("Qinterior-keep", NULL, NULL);
}
if (qh DELAUNAY && qh HALFspace) {
qh_fprintf(qh ferr, 6046, "qhull input error: can not use Delaunay('d') or Voronoi('v') with halfspace intersection('H')\n");
qh_errexit(qh_ERRinput, NULL, NULL);
}
if (!qh DELAUNAY && (qh UPPERdelaunay || qh ATinfinity)) {
qh_fprintf(qh ferr, 6047, "qhull input error: use upper-Delaunay('Qu') or infinity-point('Qz') with Delaunay('d') or Voronoi('v')\n");
qh_errexit(qh_ERRinput, NULL, NULL);
}
if (qh UPPERdelaunay && qh ATinfinity) {
qh_fprintf(qh ferr, 6048, "qhull input error: can not use infinity-point('Qz') with upper-Delaunay('Qu')\n");
qh_errexit(qh_ERRinput, NULL, NULL);
}
if (qh SCALElast && !qh DELAUNAY && qh PRINTprecision)
qh_fprintf(qh ferr, 7040, "qhull input warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
qh DOcheckmax= (!qh SKIPcheckmax && qh MERGING );
qh KEEPnearinside= (qh DOcheckmax && !(qh KEEPinside && qh KEEPcoplanar)
&& !qh NOnearinside);
if (qh MERGING)
qh CENTERtype= qh_AScentrum;
else if (qh VORONOI)
qh CENTERtype= qh_ASvoronoi;
if (qh TESTvneighbors && !qh MERGING) {
qh_fprintf(qh ferr, 6049, "qhull input error: test vertex neighbors('Qv') needs a merge option\n");
qh_errexit(qh_ERRinput, NULL ,NULL);
}
if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay)) {
qh hull_dim -= qh PROJECTinput;
if (qh DELAUNAY) {
qh hull_dim++;
if (qh ATinfinity)
extra= 1;
}
}
if (qh hull_dim <= 1) {
qh_fprintf(qh ferr, 6050, "qhull error: dimension %d must be > 1\n", qh hull_dim);
qh_errexit(qh_ERRinput, NULL, NULL);
}
for (k=2, factorial=1.0; k < qh hull_dim; k++)
factorial *= k;
qh AREAfactor= 1.0 / factorial;
trace2((qh ferr, 2005, "qh_initqhull_globals: initialize globals. dim %d numpoints %d malloc? %d projected %d to hull_dim %d\n",
dim, numpoints, ismalloc, qh PROJECTinput, qh hull_dim));
qh normal_size= qh hull_dim * sizeof(coordT);
qh center_size= qh normal_size - sizeof(coordT);
pointsneeded= qh hull_dim+1;
if (qh hull_dim > qh_DIMmergeVertex) {
qh MERGEvertices= False;
qh_option("Q3-no-merge-vertices-dim-high", NULL, NULL);
}
if (qh GOODpoint)
pointsneeded++;
#ifdef qh_NOtrace
if (qh IStracing) {
qh_fprintf(qh ferr, 6051, "qhull input error: tracing is not installed(qh_NOtrace in user.h)");
qh_errexit(qh_ERRqhull, NULL, NULL);
}
#endif
if (qh RERUN > 1) {
qh TRACElastrun= qh IStracing; /* qh_build_withrestart duplicates next conditional */
if (qh IStracing != -1)
qh IStracing= 0;
}else if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
qh TRACElevel= (qh IStracing? qh IStracing : 3);
qh IStracing= 0;
}
if (qh ROTATErandom == 0 || qh ROTATErandom == -1) {
seed= (int)time(&timedata);
if (qh ROTATErandom == -1) {
seed= -seed;
qh_option("QRandom-seed", &seed, NULL );
}else
qh_option("QRotate-random", &seed, NULL);
qh ROTATErandom= seed;
}
seed= qh ROTATErandom;
if (seed == INT_MIN) /* default value */
seed= 1;
else if (seed < 0)
seed= -seed;
qh_RANDOMseed_(seed);
randr= 0.0;
for (i=1000; i--; ) {
randi= qh_RANDOMint;
randr += randi;
if (randi > qh_RANDOMmax) {
qh_fprintf(qh ferr, 8036, "\
qhull configuration error (qh_RANDOMmax in user.h):\n\
random integer %d > qh_RANDOMmax(%.8g)\n",
randi, qh_RANDOMmax);
qh_errexit(qh_ERRinput, NULL, NULL);
}
}
qh_RANDOMseed_(seed);
randr = randr/1000;
if (randr < qh_RANDOMmax * 0.1
|| randr > qh_RANDOMmax * 0.9)
qh_fprintf(qh ferr, 8037, "\
qhull configuration warning (qh_RANDOMmax in user.h):\n\
average of 1000 random integers (%.2g) is much different than expected (%.2g).\n\
Is qh_RANDOMmax (%.2g) wrong?\n",
randr, qh_RANDOMmax * 0.5, qh_RANDOMmax);
qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax;
qh RANDOMb= 1.0 - qh RANDOMfactor;
if (qh_HASHfactor < 1.1) {
qh_fprintf(qh ferr, 6052, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1. Qhull uses linear hash probing\n",
qh_HASHfactor);
qh_errexit(qh_ERRqhull, NULL, NULL);
}
if (numpoints+extra < pointsneeded) {
qh_fprintf(qh ferr, 6214, "qhull input error: not enough points(%d) to construct initial simplex (need %d)\n",
numpoints, pointsneeded);
qh_errexit(qh_ERRinput, NULL, NULL);
}
qh_initqhull_outputflags();
} /* initqhull_globals */
/*---------------------------------
qh_initqhull_mem( )
initialize mem.c for qhull
qh.hull_dim and qh.normal_size determine some of the allocation sizes
if qh.MERGING,
includes ridgeT
calls qh_user_memsizes() to add up to 10 additional sizes for quick allocation
(see numsizes below)
returns:
mem.c already for qh_memalloc/qh_memfree (errors if called beforehand)
notes:
qh_produceoutput() prints memsizes
*/
void qh_initqhull_mem(void) {
int numsizes;
int i;
numsizes= 8+10;
qh_meminitbuffers(qh IStracing, qh_MEMalign, numsizes,
qh_MEMbufsize,qh_MEMinitbuf);
qh_memsize((int)sizeof(vertexT));
if (qh MERGING) {
qh_memsize((int)sizeof(ridgeT));
qh_memsize((int)sizeof(mergeT));
}
qh_memsize((int)sizeof(facetT));
i= sizeof(setT) + (qh hull_dim - 1) * SETelemsize; /* ridge.vertices */
qh_memsize(i);
qh_memsize(qh normal_size); /* normal */
i += SETelemsize; /* facet.vertices, .ridges, .neighbors */
qh_memsize(i);
qh_user_memsizes();
qh_memsetup();
} /* initqhull_mem */
/*---------------------------------
qh_initqhull_outputflags
initialize flags concerned with output
returns:
adjust user flags as needed
see:
qh_clear_outputflags() resets the flags
design:
test for qh.PRINTgood (i.e., only print 'good' facets)
check for conflicting print output options
*/
void qh_initqhull_outputflags(void) {
boolT printgeom= False, printmath= False, printcoplanar= False;
int i;
trace3((qh ferr, 3024, "qh_initqhull_outputflags: %s\n", qh qhull_command));
if (!(qh PRINTgood || qh PRINTneighbors)) {
if (qh KEEParea || qh KEEPminArea < REALmax/2 || qh KEEPmerge || qh DELAUNAY
|| (!qh ONLYgood && (qh GOODvertex || qh GOODpoint))) {
qh PRINTgood= True;
qh_option("Pgood", NULL, NULL);
}
}
if (qh PRINTtransparent) {
if (qh hull_dim != 4 || !qh DELAUNAY || qh VORONOI || qh DROPdim >= 0) {
qh_fprintf(qh ferr, 6215, "qhull input error: transparent Delaunay('Gt') needs 3-d Delaunay('d') w/o 'GDn'\n");
qh_errexit(qh_ERRinput, NULL, NULL);
}
qh DROPdim = 3;
qh PRINTridges = True;
}
for (i=qh_PRINTEND; i--; ) {
if (qh PRINTout[i] == qh_PRINTgeom)
printgeom= True;
else if (qh PRINTout[i] == qh_PRINTmathematica || qh PRINTout[i] == qh_PRINTmaple)
printmath= True;
else if (qh PRINTout[i] == qh_PRINTcoplanars)
printcoplanar= True;
else if (qh PRINTout[i] == qh_PRINTpointnearest)
printcoplanar= True;
else if (qh PRINTout[i] == qh_PRINTpointintersect && !qh HALFspace) {
qh_fprintf(qh ferr, 6053, "qhull input error: option 'Fp' is only used for \nhalfspace intersection('Hn,n,n').\n");
qh_errexit(qh_ERRinput, NULL, NULL);
}else if (qh PRINTout[i] == qh_PRINTtriangles && (qh HALFspace || qh VORONOI)) {
qh_fprintf(qh ferr, 6054, "qhull input error: option 'Ft' is not available for Voronoi vertices or halfspace intersection\n");
qh_errexit(qh_ERRinput, NULL, NULL);
}else if (qh PRINTout[i] == qh_PRINTcentrums && qh VORONOI) {
qh_fprintf(qh ferr, 6055, "qhull input error: option 'FC' is not available for Voronoi vertices('v')\n");
qh_errexit(qh_ERRinput, NULL, NULL);
}else if (qh PRINTout[i] == qh_PRINTvertices) {
if (qh VORONOI)
qh_option("Fvoronoi", NULL, NULL);
else
qh_option("Fvertices", NULL, NULL);
}
}
if (printcoplanar && qh DELAUNAY && qh JOGGLEmax < REALmax/2) {
if (qh PRINTprecision)
qh_fprintf(qh ferr, 7041, "qhull input warning: 'QJ' (joggle) will usually prevent coincident input sites for options 'Fc' and 'FP'\n");
}
if (printmath && (qh hull_dim > 3 || qh VORONOI)) {
qh_fprintf(qh ferr, 6056, "qhull input error: Mathematica and Maple output is only available for 2-d and 3-d convex hulls and 2-d Delaunay triangulations\n");
qh_errexit(qh_ERRinput, NULL, NULL);
}
if (printgeom) {
if (qh hull_dim > 4) {
qh_fprintf(qh ferr, 6057, "qhull input error: Geomview output is only available for 2-d, 3-d and 4-d\n");
qh_errexit(qh_ERRinput, NULL, NULL);
}
if (qh PRINTnoplanes && !(qh PRINTcoplanar + qh PRINTcentrums
+ qh PRINTdots + qh PRINTspheres + qh DOintersections + qh PRINTridges)) {
qh_fprintf(qh ferr, 6058, "qhull input error: no output specified for Geomview\n");
qh_errexit(qh_ERRinput, NULL, NULL);
}
if (qh VORONOI && (qh hull_dim > 3 || qh DROPdim >= 0)) {
qh_fprintf(qh ferr, 6059, "qhull input error: Geomview output for Voronoi diagrams only for 2-d\n");
qh_errexit(qh_ERRinput, NULL, NULL);
}
/* can not warn about furthest-site Geomview output: no lower_threshold */
if (qh hull_dim == 4 && qh DROPdim == -1 &&
(qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
qh_fprintf(qh ferr, 7042, "qhull input warning: coplanars, vertices, and centrums output not\n\
available for 4-d output(ignored). Could use 'GDn' instead.\n");
qh PRINTcoplanar= qh PRINTspheres= qh PRINTcentrums= False;
}
}
if (!qh KEEPcoplanar && !qh KEEPinside && !qh ONLYgood) {
if ((qh PRINTcoplanar && qh PRINTspheres) || printcoplanar) {
if (qh QHULLfinished) {
qh_fprintf(qh ferr, 7072, "qhull output warning: ignoring coplanar points, option 'Qc' was not set for the first run of qhull.\n");
}else {
qh KEEPcoplanar = True;
qh_option("Qcoplanar", NULL, NULL);
}
}
}
qh PRINTdim= qh hull_dim;
if (qh DROPdim >=0) { /* after Geomview checks */
if (qh DROPdim < qh hull_dim) {
qh PRINTdim--;
if (!printgeom || qh hull_dim < 3)
qh_fprintf(qh ferr, 7043, "qhull input warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh DROPdim);
}else
qh DROPdim= -1;
}else if (qh VORONOI) {
qh DROPdim= qh hull_dim-1;
qh PRINTdim= qh hull_dim-1;
}
} /* qh_initqhull_outputflags */
/*---------------------------------
qh_initqhull_start( infile, outfile, errfile )
allocate memory if needed and call qh_initqhull_start2()
*/
void qh_initqhull_start(FILE *infile, FILE *outfile, FILE *errfile) {
#if qh_QHpointer
if (qh_qh) {
qh_fprintf(errfile, 6205, "qhull error (qh_initqhull_start): qh_qh already defined. Call qh_save_qhull() first\n");
qh_exit(qh_ERRqhull); /* no error handler */
}
if (!(qh_qh= (qhT *)qh_malloc(sizeof(qhT)))) {
qh_fprintf(errfile, 6060, "qhull error (qh_initqhull_start): insufficient memory\n");
qh_exit(qh_ERRmem); /* no error handler */
}
#endif
qh_initstatistics();
qh_initqhull_start2(infile, outfile, errfile);
} /* initqhull_start */
/*---------------------------------
qh_initqhull_start2( infile, outfile, errfile )
start initialization of qhull
initialize statistics, stdio, default values for global variables
assumes qh_qh is defined
notes:
report errors elsewhere, error handling and g_qhull_output [Qhull.cpp, QhullQh()] not in initialized
see:
qh_maxmin() determines the precision constants
qh_freeqhull2()
*/
void qh_initqhull_start2(FILE *infile, FILE *outfile, FILE *errfile) {
time_t timedata;
int seed;
qh_CPUclock; /* start the clock(for qh_clock). One-shot. */
#if qh_QHpointer
memset((char *)qh_qh, 0, sizeof(qhT)); /* every field is 0, FALSE, NULL */
#else
memset((char *)&qh_qh, 0, sizeof(qhT));
#endif
qh ANGLEmerge= True;
qh DROPdim= -1;
qh ferr= errfile;
qh fin= infile;
qh fout= outfile;
qh furthest_id= -1;
qh JOGGLEmax= REALmax;
qh KEEPminArea = REALmax;
qh last_low= REALmax;
qh last_high= REALmax;
qh last_newhigh= REALmax;
qh max_outside= 0.0;
qh max_vertex= 0.0;
qh MAXabs_coord= 0.0;
qh MAXsumcoord= 0.0;
qh MAXwidth= -REALmax;
qh MERGEindependent= True;
qh MINdenom_1= fmax_(1.0/REALmax, REALmin); /* used by qh_scalepoints */
qh MINoutside= 0.0;
qh MINvisible= REALmax;
qh MAXcoplanar= REALmax;
qh outside_err= REALmax;
qh premerge_centrum= 0.0;
qh premerge_cos= REALmax;
qh PRINTprecision= True;
qh PRINTradius= 0.0;
qh postmerge_cos= REALmax;
qh postmerge_centrum= 0.0;
qh ROTATErandom= INT_MIN;
qh MERGEvertices= True;
qh totarea= 0.0;
qh totvol= 0.0;
qh TRACEdist= REALmax;
qh TRACEpoint= -1; /* recompile or use 'TPn' */
qh tracefacet_id= UINT_MAX; /* recompile to trace a facet */
qh tracevertex_id= UINT_MAX; /* recompile to trace a vertex */
seed= (int)time(&timedata);
qh_RANDOMseed_(seed);
- qh run_id= qh_RANDOMint+1; /* disallow 0 [UsingLibQhull::NOqhRunId] */
+ qh->run_id= qh_RANDOMint;
+ if(!qh->run_id)
+ qh->run_id++; /* guarantee non-zero */
qh_option("run-id", &qh run_id, NULL);
strcat(qh qhull, "qhull");
} /* initqhull_start2 */
/*---------------------------------
qh_initthresholds( commandString )
set thresholds for printing and scaling from commandString
returns:
sets qh.GOODthreshold or qh.SPLITthreshold if 'Pd0D1' used
see:
qh_initflags(), 'Qbk' 'QBk' 'Pdk' and 'PDk'
qh_inthresholds()
design:
for each 'Pdn' or 'PDn' option
check syntax
set qh.lower_threshold or qh.upper_threshold
set qh.GOODthreshold if an unbounded threshold is used
set qh.SPLITthreshold if a bounded threshold is used
*/
void qh_initthresholds(char *command) {
realT value;
int idx, maxdim, k;
char *s= command; /* non-const due to strtol */
char key;
maxdim= qh input_dim;
if (qh DELAUNAY && (qh PROJECTdelaunay || qh PROJECTinput))
maxdim++;
while (*s) {
if (*s == '-')
s++;
if (*s == 'P') {
s++;
while (*s && !isspace(key= *s++)) {
if (key == 'd' || key == 'D') {
if (!isdigit(*s)) {
qh_fprintf(qh ferr, 7044, "qhull warning: no dimension given for Print option '%c' at: %s. Ignored\n",
key, s-1);
continue;
}
idx= qh_strtol(s, &s);
if (idx >= qh hull_dim) {
qh_fprintf(qh ferr, 7045, "qhull warning: dimension %d for Print option '%c' is >= %d. Ignored\n",
idx, key, qh hull_dim);
continue;
}
if (*s == ':') {
s++;
value= qh_strtod(s, &s);
if (fabs((double)value) > 1.0) {
qh_fprintf(qh ferr, 7046, "qhull warning: value %2.4g for Print option %c is > +1 or < -1. Ignored\n",
value, key);
continue;
}
}else
value= 0.0;
if (key == 'd')
qh lower_threshold[idx]= value;
else
qh upper_threshold[idx]= value;
}
}
}else if (*s == 'Q') {
s++;
while (*s && !isspace(key= *s++)) {
if (key == 'b' && *s == 'B') {
s++;
for (k=maxdim; k--; ) {
qh lower_bound[k]= -qh_DEFAULTbox;
qh upper_bound[k]= qh_DEFAULTbox;
}
}else if (key == 'b' && *s == 'b')
s++;
else if (key == 'b' || key == 'B') {
if (!isdigit(*s)) {
qh_fprintf(qh ferr, 7047, "qhull warning: no dimension given for Qhull option %c. Ignored\n",
key);
continue;
}
idx= qh_strtol(s, &s);
if (idx >= maxdim) {
qh_fprintf(qh ferr, 7048, "qhull warning: dimension %d for Qhull option %c is >= %d. Ignored\n",
idx, key, maxdim);
continue;
}
if (*s == ':') {
s++;
value= qh_strtod(s, &s);
}else if (key == 'b')
value= -qh_DEFAULTbox;
else
value= qh_DEFAULTbox;
if (key == 'b')
qh lower_bound[idx]= value;
else
qh upper_bound[idx]= value;
}
}
}else {
while (*s && !isspace(*s))
s++;
}
while (isspace(*s))
s++;
}
for (k=qh hull_dim; k--; ) {
if (qh lower_threshold[k] > -REALmax/2) {
qh GOODthreshold= True;
if (qh upper_threshold[k] < REALmax/2) {
qh SPLITthresholds= True;
qh GOODthreshold= False;
break;
}
}else if (qh upper_threshold[k] < REALmax/2)
qh GOODthreshold= True;
}
} /* initthresholds */
/*---------------------------------
qh_option( option, intVal, realVal )
add an option description to qh.qhull_options
notes:
NOerrors -- qh_option can not call qh_errexit() [qh_initqhull_start2]
will be printed with statistics ('Ts') and errors
strlen(option) < 40
*/
void qh_option(const char *option, int *i, realT *r) {
char buf[200];
int len, maxlen;
sprintf(buf, " %s", option);
if (i)
sprintf(buf+strlen(buf), " %d", *i);
if (r)
sprintf(buf+strlen(buf), " %2.2g", *r);
len= (int)strlen(buf); /* WARN64 */
qh qhull_optionlen += len;
maxlen= sizeof(qh qhull_options) - len -1;
maximize_(maxlen, 0);
if (qh qhull_optionlen >= qh_OPTIONline && maxlen > 0) {
qh qhull_optionlen= len;
strncat(qh qhull_options, "\n", (size_t)(maxlen--));
}
strncat(qh qhull_options, buf, (size_t)maxlen);
} /* option */
#if qh_QHpointer
/*---------------------------------
qh_restore_qhull( oldqh )
restores a previously saved qhull
also restores qh_qhstat and qhmem.tempstack
Sets *oldqh to NULL
notes:
errors if current qhull hasn't been saved or freed
uses qhmem for error reporting
NOTE 1998/5/11:
Freeing memory after qh_save_qhull and qh_restore_qhull
is complicated. The procedures will be redesigned.
see:
qh_save_qhull(), UsingLibQhull
*/
void qh_restore_qhull(qhT **oldqh) {
if (*oldqh && strcmp((*oldqh)->qhull, "qhull")) {
qh_fprintf(qhmem.ferr, 6061, "qhull internal error (qh_restore_qhull): %p is not a qhull data structure\n",
*oldqh);
qh_errexit(qh_ERRqhull, NULL, NULL);
}
if (qh_qh) {
qh_fprintf(qhmem.ferr, 6062, "qhull internal error (qh_restore_qhull): did not save or free existing qhull\n");
qh_errexit(qh_ERRqhull, NULL, NULL);
}
if (!*oldqh || !(*oldqh)->old_qhstat) {
qh_fprintf(qhmem.ferr, 6063, "qhull internal error (qh_restore_qhull): did not previously save qhull %p\n",
*oldqh);
qh_errexit(qh_ERRqhull, NULL, NULL);
}
qh_qh= *oldqh;
*oldqh= NULL;
qh_qhstat= qh old_qhstat;
qhmem.tempstack= qh old_tempstack;
qh old_qhstat= 0;
qh old_tempstack= 0;
trace1((qh ferr, 1007, "qh_restore_qhull: restored qhull from %p\n", *oldqh));
} /* restore_qhull */
/*---------------------------------
qh_save_qhull( )
saves qhull for a later qh_restore_qhull
also saves qh_qhstat and qhmem.tempstack
returns:
qh_qh=NULL
notes:
need to initialize qhull or call qh_restore_qhull before continuing
NOTE 1998/5/11:
Freeing memory after qh_save_qhull and qh_restore_qhull
is complicated. The procedures will be redesigned.
see:
qh_restore_qhull()
*/
qhT *qh_save_qhull(void) {
qhT *oldqh;
trace1((qhmem.ferr, 1045, "qh_save_qhull: save qhull %p\n", qh_qh));
if (!qh_qh) {
qh_fprintf(qhmem.ferr, 6064, "qhull internal error (qh_save_qhull): qhull not initialized\n");
qh_errexit(qh_ERRqhull, NULL, NULL);
}
qh old_qhstat= qh_qhstat;
qh_qhstat= NULL;
qh old_tempstack= qhmem.tempstack;
qhmem.tempstack= NULL;
oldqh= qh_qh;
qh_qh= NULL;
return oldqh;
} /* save_qhull */
#endif
diff --git a/src/libqhull/libqhull.h b/src/libqhull/libqhull.h
index 1d05958..6762352 100644
--- a/src/libqhull/libqhull.h
+++ b/src/libqhull/libqhull.h
@@ -1,1100 +1,1101 @@
/* ---------------------------------
libqhull.h
user-level header file for using qhull.a library
see qh-qhull.htm, qhull_a.h
Copyright (c) 1993-2014 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/libqhull.h#9 $$Change: 1651 $
- $DateTime: 2014/01/17 08:13:57 $$Author: bbarber $
+ $Id: //main/2011/qhull/src/libqhull/libqhull.h#10 $$Change: 1708 $
+ $DateTime: 2014/03/26 19:13:56 $$Author: bbarber $
NOTE: access to qh_qh is via the 'qh' macro. This allows
qh_qh to be either a pointer or a structure. An example
of using qh is "qh.DROPdim" which accesses the DROPdim
field of qh_qh. Similarly, access to qh_qhstat is via
the 'qhstat' macro.
includes function prototypes for libqhull.c, geom.c, global.c, io.c, user.c
use mem.h for mem.c
use qset.h for qset.c
see unix.c for an example of using libqhull.h
recompile qhull if you change this file
*/
#ifndef qhDEFlibqhull
#define qhDEFlibqhull 1
/*=========================== -included files ==============*/
#include "user.h" /* user definable constants (e.g., qh_QHpointer) */
#include
#include
#include
#include
#if __MWERKS__ && __POWERPC__
#include
#include
#include
#endif
#ifndef __STDC__
#ifndef __cplusplus
#if !_MSC_VER
#error Neither __STDC__ nor __cplusplus is defined. Please use strict ANSI C or C++ to compile
#error Qhull. You may need to turn off compiler extensions in your project configuration. If
#error your compiler is a standard C compiler, you can delete this warning from libqhull.h
#endif
#endif
#endif
/*============ constants and basic types ====================*/
extern const char *qh_version; /* defined in global.c */
/*----------------------------------
coordT
coordinates and coefficients are stored as realT (i.e., double)
notes:
Qhull works well if realT is 'float'. If so joggle (QJ) is not effective.
Could use 'float' for data and 'double' for calculations (realT vs. coordT)
This requires many type casts, and adjusted error bounds.
Also C compilers may do expressions in double anyway.
*/
#define coordT realT
/*----------------------------------
pointT
a point is an array of coordinates, usually qh.hull_dim
*/
#define pointT coordT
/*----------------------------------
flagT
Boolean flag as a bit
*/
#define flagT unsigned int
/*----------------------------------
boolT
boolean value, either True or False
notes:
needed for portability
Use qh_False/qh_True as synonyms
*/
#define boolT unsigned int
#ifdef False
#undef False
#endif
#ifdef True
#undef True
#endif
#define False 0
#define True 1
#define qh_False 0
#define qh_True 1
/*----------------------------------
qh_CENTER
to distinguish facet->center
*/
typedef enum
{
qh_ASnone = 0, qh_ASvoronoi, qh_AScentrum
}
qh_CENTER;
/*----------------------------------
qh_PRINT
output formats for printing (qh.PRINTout).
'Fa' 'FV' 'Fc' 'FC'
notes:
some of these names are similar to qhT names. The similar names are only
used in switch statements in qh_printbegin() etc.
*/
typedef enum {qh_PRINTnone= 0,
qh_PRINTarea, qh_PRINTaverage, /* 'Fa' 'FV' 'Fc' 'FC' */
qh_PRINTcoplanars, qh_PRINTcentrums,
qh_PRINTfacets, qh_PRINTfacets_xridge, /* 'f' 'FF' 'G' 'FI' 'Fi' 'Fn' */
qh_PRINTgeom, qh_PRINTids, qh_PRINTinner, qh_PRINTneighbors,
qh_PRINTnormals, qh_PRINTouter, qh_PRINTmaple, /* 'n' 'Fo' 'i' 'm' 'Fm' 'FM', 'o' */
qh_PRINTincidences, qh_PRINTmathematica, qh_PRINTmerges, qh_PRINToff,
qh_PRINToptions, qh_PRINTpointintersect, /* 'FO' 'Fp' 'FP' 'p' 'FQ' 'FS' */
qh_PRINTpointnearest, qh_PRINTpoints, qh_PRINTqhull, qh_PRINTsize,
qh_PRINTsummary, qh_PRINTtriangles, /* 'Fs' 'Ft' 'Fv' 'FN' 'Fx' */
qh_PRINTvertices, qh_PRINTvneighbors, qh_PRINTextremes,
qh_PRINTEND} qh_PRINT;
/*----------------------------------
qh_ALL
argument flag for selecting everything
*/
#define qh_ALL True
#define qh_NOupper True /* argument for qh_findbest */
#define qh_IScheckmax True /* argument for qh_findbesthorizon */
#define qh_ISnewfacets True /* argument for qh_findbest */
#define qh_RESETvisible True /* argument for qh_resetlists */
/*----------------------------------
qh_ERR
Qhull exit codes, for indicating errors
See: MSG_ERROR and MSG_WARNING [user.h]
*/
#define qh_ERRnone 0 /* no error occurred during qhull */
#define qh_ERRinput 1 /* input inconsistency */
#define qh_ERRsingular 2 /* singular input data */
#define qh_ERRprec 3 /* precision error */
#define qh_ERRmem 4 /* insufficient memory, matches mem.h */
#define qh_ERRqhull 5 /* internal error detected, matches mem.h */
/*----------------------------------
qh_FILEstderr
Fake stderr to distinguish error output from normal output
For C++ interface. Must redefine qh_fprintf_qhull
*/
#define qh_FILEstderr ((FILE*)1)
/* ============ -structures- ====================
each of the following structures is defined by a typedef
all realT and coordT fields occur at the beginning of a structure
(otherwise space may be wasted due to alignment)
define all flags together and pack into 32-bit number
*/
typedef struct vertexT vertexT;
typedef struct ridgeT ridgeT;
typedef struct facetT facetT;
#ifndef DEFsetT
#define DEFsetT 1
typedef struct setT setT; /* defined in qset.h */
#endif
#ifndef DEFqhstatT
#define DEFqhstatT 1
typedef struct qhstatT qhstatT; /* defined in stat.h */
#endif
/*----------------------------------
facetT
defines a facet
notes:
qhull() generates the hull as a list of facets.
topological information:
f.previous,next doubly-linked list of facets
f.vertices set of vertices
f.ridges set of ridges
f.neighbors set of neighbors
f.toporient True if facet has top-orientation (else bottom)
geometric information:
f.offset,normal hyperplane equation
f.maxoutside offset to outer plane -- all points inside
f.center centrum for testing convexity
f.simplicial True if facet is simplicial
f.flipped True if facet does not include qh.interior_point
for constructing hull:
f.visible True if facet on list of visible facets (will be deleted)
f.newfacet True if facet on list of newly created facets
f.coplanarset set of points coplanar with this facet
(includes near-inside points for later testing)
f.outsideset set of points outside of this facet
f.furthestdist distance to furthest point of outside set
f.visitid marks visited facets during a loop
f.replace replacement facet for to-be-deleted, visible facets
f.samecycle,newcycle cycle of facets for merging into horizon facet
see below for other flags and fields
*/
struct facetT {
#if !qh_COMPUTEfurthest
coordT furthestdist;/* distance to furthest point of outsideset */
#endif
#if qh_MAXoutside
coordT maxoutside; /* max computed distance of point to facet
Before QHULLfinished this is an approximation
since maxdist not always set for mergefacet
Actual outer plane is +DISTround and
computed outer plane is +2*DISTround */
#endif
coordT offset; /* exact offset of hyperplane from origin */
coordT *normal; /* normal of hyperplane, hull_dim coefficients */
/* if tricoplanar, shared with a neighbor */
union { /* in order of testing */
realT area; /* area of facet, only in io.c if ->isarea */
facetT *replace; /* replacement facet if ->visible and NEWfacets
is NULL only if qh_mergedegen_redundant or interior */
facetT *samecycle; /* cycle of facets from the same visible/horizon intersection,
if ->newfacet */
facetT *newcycle; /* in horizon facet, current samecycle of new facets */
facetT *trivisible; /* visible facet for ->tricoplanar facets during qh_triangulate() */
facetT *triowner; /* owner facet for ->tricoplanar, !isarea facets w/ ->keepcentrum */
}f;
coordT *center; /* centrum for convexity, qh.CENTERtype == qh_AScentrum */
/* Voronoi center, qh.CENTERtype == qh_ASvoronoi */
/* if tricoplanar, shared with a neighbor */
facetT *previous; /* previous facet in the facet_list */
facetT *next; /* next facet in the facet_list */
setT *vertices; /* vertices for this facet, inverse sorted by ID
if simplicial, 1st vertex was apex/furthest */
setT *ridges; /* explicit ridges for nonsimplicial facets.
for simplicial facets, neighbors define the ridges */
setT *neighbors; /* neighbors of the facet. If simplicial, the kth
neighbor is opposite the kth vertex, and the first
neighbor is the horizon facet for the first vertex*/
setT *outsideset; /* set of points outside this facet
if non-empty, last point is furthest
if NARROWhull, includes coplanars for partitioning*/
setT *coplanarset; /* set of points coplanar with this facet
> qh.min_vertex and <= facet->max_outside
a point is assigned to the furthest facet
if non-empty, last point is furthest away */
unsigned visitid; /* visit_id, for visiting all neighbors,
all uses are independent */
unsigned id; /* unique identifier from qh.facet_id */
unsigned nummerge:9; /* number of merges */
#define qh_MAXnummerge 511 /* 2^9-1, 32 flags total, see "flags:" in io.c */
flagT tricoplanar:1; /* True if TRIangulate and simplicial and coplanar with a neighbor */
/* all tricoplanars share the same ->center, ->normal, ->offset, ->maxoutside */
/* all tricoplanars share the same apex */
/* if ->degenerate, does not span facet (one logical ridge) */
/* one tricoplanar has ->keepcentrum and ->coplanarset */
/* during qh_triangulate, f.trivisible points to original facet */
flagT newfacet:1; /* True if facet on qh.newfacet_list (new or merged) */
flagT visible:1; /* True if visible facet (will be deleted) */
flagT toporient:1; /* True if created with top orientation
after merging, use ridge orientation */
flagT simplicial:1;/* True if simplicial facet, ->ridges may be implicit */
flagT seen:1; /* used to perform operations only once, like visitid */
flagT seen2:1; /* used to perform operations only once, like visitid */
flagT flipped:1; /* True if facet is flipped */
flagT upperdelaunay:1; /* True if facet is upper envelope of Delaunay triangulation */
flagT notfurthest:1; /* True if last point of outsideset is not furthest*/
/*-------- flags primarily for output ---------*/
flagT good:1; /* True if a facet marked good for output */
flagT isarea:1; /* True if facet->f.area is defined */
/*-------- flags for merging ------------------*/
flagT dupridge:1; /* True if duplicate ridge in facet */
flagT mergeridge:1; /* True if facet or neighbor contains a qh_MERGEridge
->normal defined (also defined for mergeridge2) */
flagT mergeridge2:1; /* True if neighbor contains a qh_MERGEridge (mark_dupridges */
flagT coplanar:1; /* True if horizon facet is coplanar at last use */
flagT mergehorizon:1; /* True if will merge into horizon (->coplanar) */
flagT cycledone:1;/* True if mergecycle_all already done */
flagT tested:1; /* True if facet convexity has been tested (false after merge */
flagT keepcentrum:1; /* True if keep old centrum after a merge, or marks owner for ->tricoplanar */
flagT newmerge:1; /* True if facet is newly merged for reducevertices */
flagT degenerate:1; /* True if facet is degenerate (degen_mergeset or ->tricoplanar) */
flagT redundant:1; /* True if facet is redundant (degen_mergeset) */
};
/*----------------------------------
ridgeT
defines a ridge
notes:
a ridge is hull_dim-1 simplex between two neighboring facets. If the
facets are non-simplicial, there may be more than one ridge between
two facets. E.G. a 4-d hypercube has two triangles between each pair
of neighboring facets.
topological information:
vertices a set of vertices
top,bottom neighboring facets with orientation
geometric information:
tested True if ridge is clearly convex
nonconvex True if ridge is non-convex
*/
struct ridgeT {
setT *vertices; /* vertices belonging to this ridge, inverse sorted by ID
NULL if a degen ridge (matchsame) */
facetT *top; /* top facet this ridge is part of */
facetT *bottom; /* bottom facet this ridge is part of */
unsigned id:24; /* unique identifier, =>room for 8 flags, bit field matches qh.ridge_id */
flagT seen:1; /* used to perform operations only once */
flagT tested:1; /* True when ridge is tested for convexity */
flagT nonconvex:1; /* True if getmergeset detected a non-convex neighbor
only one ridge between neighbors may have nonconvex */
};
/*----------------------------------
vertexT
defines a vertex
topological information:
next,previous doubly-linked list of all vertices
neighbors set of adjacent facets (only if qh.VERTEXneighbors)
geometric information:
point array of DIM3 coordinates
*/
struct vertexT {
vertexT *next; /* next vertex in vertex_list */
vertexT *previous; /* previous vertex in vertex_list */
pointT *point; /* hull_dim coordinates (coordT) */
setT *neighbors; /* neighboring facets of vertex, qh_vertexneighbors()
inits in io.c or after first merge */
unsigned visitid:31; /* for use with qh.vertex_visit, size must match */
flagT seen2:1; /* another seen flag */
unsigned id:24; /* unique identifier, bit field matches qh.vertex_id */
unsigned dim:4; /* dimension of point if non-zero, used by cpp */
/* =>room for 4 flags */
flagT seen:1; /* used to perform operations only once */
flagT delridge:1; /* vertex was part of a deleted ridge */
flagT deleted:1; /* true if vertex on qh.del_vertices */
flagT newlist:1; /* true if vertex on qh.newvertex_list */
};
#define MAX_vdim 15 /* Maximum size of vertex->dim */
/*======= -global variables -qh ============================*/
/*----------------------------------
qh
all global variables for qhull are in qh, qhmem, and qhstat
notes:
qhmem is defined in mem.h, qhstat is defined in stat.h, qhrbox is defined in rboxpoints.h
Access to qh_qh is via the "qh" macro. See qh_QHpointer in user.h
All global variables for qhull are in qh, qhmem, and qhstat
qh must be unique for each instance of qhull
qhstat may be shared between qhull instances.
qhmem may be shared across multiple instances of Qhull.
Rbox uses global variables rbox_inuse and rbox, but does not persist data across calls.
Qhull is not multithreaded. Global state could be stored in thread-local storage.
*/
extern int qhull_inuse;
typedef struct qhT qhT;
#if qh_QHpointer_dllimport
#define qh qh_qh->
__declspec(dllimport) extern qhT *qh_qh; /* allocated in global.c */
#elif qh_QHpointer
#define qh qh_qh->
extern qhT *qh_qh; /* allocated in global.c */
#elif qh_dllimport
#define qh qh_qh.
__declspec(dllimport) extern qhT qh_qh; /* allocated in global.c */
#else
#define qh qh_qh.
extern qhT qh_qh;
#endif
struct qhT {
/*----------------------------------
qh constants
configuration flags and constants for Qhull
notes:
The user configures Qhull by defining flags. They are
copied into qh by qh_setflags(). qh-quick.htm#options defines the flags.
*/
boolT ALLpoints; /* true 'Qs' if search all points for initial simplex */
boolT ANGLEmerge; /* true 'Qa' if sort potential merges by angle */
boolT APPROXhull; /* true 'Wn' if MINoutside set */
realT MINoutside; /* 'Wn' min. distance for an outside point */
boolT ANNOTATEoutput; /* true 'Ta' if annotate output with message codes */
boolT ATinfinity; /* true 'Qz' if point num_points-1 is "at-infinity"
for improving precision in Delaunay triangulations */
boolT AVOIDold; /* true 'Q4' if avoid old->new merges */
boolT BESToutside; /* true 'Qf' if partition points into best outsideset */
boolT CDDinput; /* true 'Pc' if input uses CDD format (1.0/offset first) */
boolT CDDoutput; /* true 'PC' if print normals in CDD format (offset first) */
boolT CHECKfrequently; /* true 'Tc' if checking frequently */
realT premerge_cos; /* 'A-n' cos_max when pre merging */
realT postmerge_cos; /* 'An' cos_max when post merging */
boolT DELAUNAY; /* true 'd' if computing DELAUNAY triangulation */
boolT DOintersections; /* true 'Gh' if print hyperplane intersections */
int DROPdim; /* drops dim 'GDn' for 4-d -> 3-d output */
boolT FORCEoutput; /* true 'Po' if forcing output despite degeneracies */
int GOODpoint; /* 1+n for 'QGn', good facet if visible/not(-) from point n*/
pointT *GOODpointp; /* the actual point */
boolT GOODthreshold; /* true if qh.lower_threshold/upper_threshold defined
false if qh.SPLITthreshold */
int GOODvertex; /* 1+n, good facet if vertex for point n */
pointT *GOODvertexp; /* the actual point */
boolT HALFspace; /* true 'Hn,n,n' if halfspace intersection */
+ boolT ISqhullQh; /* Set by Qhull.cpp on initialization */
int IStracing; /* trace execution, 0=none, 1=least, 4=most, -1=events */
int KEEParea; /* 'PAn' number of largest facets to keep */
boolT KEEPcoplanar; /* true 'Qc' if keeping nearest facet for coplanar points */
boolT KEEPinside; /* true 'Qi' if keeping nearest facet for inside points
set automatically if 'd Qc' */
int KEEPmerge; /* 'PMn' number of facets to keep with most merges */
realT KEEPminArea; /* 'PFn' minimum facet area to keep */
realT MAXcoplanar; /* 'Un' max distance below a facet to be coplanar*/
boolT MERGEexact; /* true 'Qx' if exact merges (coplanar, degen, dupridge, flipped) */
boolT MERGEindependent; /* true 'Q2' if merging independent sets */
boolT MERGING; /* true if exact-, pre- or post-merging, with angle and centrum tests */
realT premerge_centrum; /* 'C-n' centrum_radius when pre merging. Default is round-off */
realT postmerge_centrum; /* 'Cn' centrum_radius when post merging. Default is round-off */
boolT MERGEvertices; /* true 'Q3' if merging redundant vertices */
realT MINvisible; /* 'Vn' min. distance for a facet to be visible */
boolT NOnarrow; /* true 'Q10' if no special processing for narrow distributions */
boolT NOnearinside; /* true 'Q8' if ignore near-inside points when partitioning */
boolT NOpremerge; /* true 'Q0' if no defaults for C-0 or Qx */
boolT ONLYgood; /* true 'Qg' if process points with good visible or horizon facets */
boolT ONLYmax; /* true 'Qm' if only process points that increase max_outside */
boolT PICKfurthest; /* true 'Q9' if process furthest of furthest points*/
boolT POSTmerge; /* true if merging after buildhull (Cn or An) */
boolT PREmerge; /* true if merging during buildhull (C-n or A-n) */
/* NOTE: some of these names are similar to qh_PRINT names */
boolT PRINTcentrums; /* true 'Gc' if printing centrums */
boolT PRINTcoplanar; /* true 'Gp' if printing coplanar points */
int PRINTdim; /* print dimension for Geomview output */
boolT PRINTdots; /* true 'Ga' if printing all points as dots */
boolT PRINTgood; /* true 'Pg' if printing good facets */
boolT PRINTinner; /* true 'Gi' if printing inner planes */
boolT PRINTneighbors; /* true 'PG' if printing neighbors of good facets */
boolT PRINTnoplanes; /* true 'Gn' if printing no planes */
boolT PRINToptions1st; /* true 'FO' if printing options to stderr */
boolT PRINTouter; /* true 'Go' if printing outer planes */
boolT PRINTprecision; /* false 'Pp' if not reporting precision problems */
qh_PRINT PRINTout[qh_PRINTEND]; /* list of output formats to print */
boolT PRINTridges; /* true 'Gr' if print ridges */
boolT PRINTspheres; /* true 'Gv' if print vertices as spheres */
boolT PRINTstatistics; /* true 'Ts' if printing statistics to stderr */
boolT PRINTsummary; /* true 's' if printing summary to stderr */
boolT PRINTtransparent; /* true 'Gt' if print transparent outer ridges */
boolT PROJECTdelaunay; /* true if DELAUNAY, no readpoints() and
need projectinput() for Delaunay in qh_init_B */
int PROJECTinput; /* number of projected dimensions 'bn:0Bn:0' */
boolT QUICKhelp; /* true if quick help message for degen input */
boolT RANDOMdist; /* true if randomly change distplane and setfacetplane */
realT RANDOMfactor; /* maximum random perturbation */
realT RANDOMa; /* qh_randomfactor is randr * RANDOMa + RANDOMb */
realT RANDOMb;
boolT RANDOMoutside; /* true if select a random outside point */
int REPORTfreq; /* buildtracing reports every n facets */
int REPORTfreq2; /* tracemerging reports every REPORTfreq/2 facets */
int RERUN; /* 'TRn' rerun qhull n times (qh.build_cnt) */
int ROTATErandom; /* 'QRn' seed, 0 time, >= rotate input */
boolT SCALEinput; /* true 'Qbk' if scaling input */
boolT SCALElast; /* true 'Qbb' if scale last coord to max prev coord */
boolT SETroundoff; /* true 'E' if qh.DISTround is predefined */
boolT SKIPcheckmax; /* true 'Q5' if skip qh_check_maxout */
boolT SKIPconvex; /* true 'Q6' if skip convexity testing during pre-merge */
boolT SPLITthresholds; /* true if upper_/lower_threshold defines a region
used only for printing (!for qh.ONLYgood) */
int STOPcone; /* 'TCn' 1+n for stopping after cone for point n */
/* also used by qh_build_withresart for err exit*/
int STOPpoint; /* 'TVn' 'TV-n' 1+n for stopping after/before(-)
adding point n */
int TESTpoints; /* 'QTn' num of test points after qh.num_points. Test points always coplanar. */
boolT TESTvneighbors; /* true 'Qv' if test vertex neighbors at end */
int TRACElevel; /* 'Tn' conditional IStracing level */
int TRACElastrun; /* qh.TRACElevel applies to last qh.RERUN */
int TRACEpoint; /* 'TPn' start tracing when point n is a vertex */
realT TRACEdist; /* 'TWn' start tracing when merge distance too big */
int TRACEmerge; /* 'TMn' start tracing before this merge */
boolT TRIangulate; /* true 'Qt' if triangulate non-simplicial facets */
boolT TRInormals; /* true 'Q11' if triangulate duplicates normals (sets Qt) */
boolT UPPERdelaunay; /* true 'Qu' if computing furthest-site Delaunay */
boolT USEstdout; /* true 'Tz' if using stdout instead of stderr */
boolT VERIFYoutput; /* true 'Tv' if verify output at end of qhull */
boolT VIRTUALmemory; /* true 'Q7' if depth-first processing in buildhull */
boolT VORONOI; /* true 'v' if computing Voronoi diagram */
/*--------input constants ---------*/
realT AREAfactor; /* 1/(hull_dim-1)! for converting det's to area */
boolT DOcheckmax; /* true if calling qh_check_maxout (qh_initqhull_globals) */
char *feasible_string; /* feasible point 'Hn,n,n' for halfspace intersection */
coordT *feasible_point; /* as coordinates, both malloc'd */
boolT GETarea; /* true 'Fa', 'FA', 'FS', 'PAn', 'PFn' if compute facet area/Voronoi volume in io.c */
boolT KEEPnearinside; /* true if near-inside points in coplanarset */
int hull_dim; /* dimension of hull, set by initbuffers */
int input_dim; /* dimension of input, set by initbuffers */
int num_points; /* number of input points */
pointT *first_point; /* array of input points, see POINTSmalloc */
boolT POINTSmalloc; /* true if qh.first_point/num_points allocated */
pointT *input_points; /* copy of original qh.first_point for input points for qh_joggleinput */
boolT input_malloc; /* true if qh.input_points malloc'd */
char qhull_command[256];/* command line that invoked this program */
int qhull_commandsiz2; /* size of qhull_command at qh_clear_outputflags */
char rbox_command[256]; /* command line that produced the input points */
char qhull_options[512];/* descriptive list of options */
int qhull_optionlen; /* length of last line */
int qhull_optionsiz; /* size of qhull_options at qh_build_withrestart */
int qhull_optionsiz2; /* size of qhull_options at qh_clear_outputflags */
int run_id; /* non-zero, random identifier for this instance of qhull */
boolT VERTEXneighbors; /* true if maintaining vertex neighbors */
boolT ZEROcentrum; /* true if 'C-0' or 'C-0 Qx'. sets ZEROall_ok */
realT *upper_threshold; /* don't print if facet->normal[k]>=upper_threshold[k]
must set either GOODthreshold or SPLITthreshold
if Delaunay, default is 0.0 for upper envelope */
realT *lower_threshold; /* don't print if facet->normal[k] <=lower_threshold[k] */
realT *upper_bound; /* scale point[k] to new upper bound */
realT *lower_bound; /* scale point[k] to new lower bound
project if both upper_ and lower_bound == 0 */
/*----------------------------------
qh precision constants
precision constants for Qhull
notes:
qh_detroundoff() computes the maximum roundoff error for distance
and other computations. It also sets default values for the
qh constants above.
*/
realT ANGLEround; /* max round off error for angles */
realT centrum_radius; /* max centrum radius for convexity (roundoff added) */
realT cos_max; /* max cosine for convexity (roundoff added) */
- realT DISTround; /* max round off error for distances, 'E' overrides */
+ realT DISTround; /* max round off error for distances, 'E' overrides qh_distround() */
realT MAXabs_coord; /* max absolute coordinate */
realT MAXlastcoord; /* max last coordinate for qh_scalelast */
realT MAXsumcoord; /* max sum of coordinates */
realT MAXwidth; /* max rectilinear width of point coordinates */
realT MINdenom_1; /* min. abs. value for 1/x */
realT MINdenom; /* use divzero if denominator < MINdenom */
realT MINdenom_1_2; /* min. abs. val for 1/x that allows normalization */
realT MINdenom_2; /* use divzero if denominator < MINdenom_2 */
realT MINlastcoord; /* min. last coordinate for qh_scalelast */
boolT NARROWhull; /* set in qh_initialhull if angle < qh_MAXnarrow */
realT *NEARzero; /* hull_dim array for near zero in gausselim */
realT NEARinside; /* keep points for qh_check_maxout if close to facet */
realT ONEmerge; /* max distance for merging simplicial facets */
realT outside_err; /* application's epsilon for coplanar points
qh_check_bestdist() qh_check_points() reports error if point outside */
realT WIDEfacet; /* size of wide facet for skipping ridge in
area computation and locking centrum */
/*----------------------------------
qh internal constants
internal constants for Qhull
*/
char qhull[sizeof("qhull")]; /* "qhull" for checking ownership while debugging */
jmp_buf errexit; /* exit label for qh_errexit, defined by setjmp() */
char jmpXtra[40]; /* extra bytes in case jmp_buf is defined wrong by compiler */
jmp_buf restartexit; /* restart label for qh_errexit, defined by setjmp() */
char jmpXtra2[40]; /* extra bytes in case jmp_buf is defined wrong by compiler*/
FILE *fin; /* pointer to input file, init by qh_meminit */
FILE *fout; /* pointer to output file */
FILE *ferr; /* pointer to error file */
pointT *interior_point; /* center point of the initial simplex*/
int normal_size; /* size in bytes for facet normals and point coords*/
int center_size; /* size in bytes for Voronoi centers */
int TEMPsize; /* size for small, temporary sets (in quick mem) */
/*----------------------------------
qh facet and vertex lists
defines lists of facets, new facets, visible facets, vertices, and
new vertices. Includes counts, next ids, and trace ids.
see:
qh_resetlists()
*/
facetT *facet_list; /* first facet */
facetT *facet_tail; /* end of facet_list (dummy facet) */
facetT *facet_next; /* next facet for buildhull()
previous facets do not have outside sets
NARROWhull: previous facets may have coplanar outside sets for qh_outcoplanar */
facetT *newfacet_list; /* list of new facets to end of facet_list */
facetT *visible_list; /* list of visible facets preceeding newfacet_list,
facet->visible set */
int num_visible; /* current number of visible facets */
unsigned tracefacet_id; /* set at init, then can print whenever */
facetT *tracefacet; /* set in newfacet/mergefacet, undone in delfacet*/
unsigned tracevertex_id; /* set at buildtracing, can print whenever */
vertexT *tracevertex; /* set in newvertex, undone in delvertex*/
vertexT *vertex_list; /* list of all vertices, to vertex_tail */
vertexT *vertex_tail; /* end of vertex_list (dummy vertex) */
vertexT *newvertex_list; /* list of vertices in newfacet_list, to vertex_tail
all vertices have 'newlist' set */
int num_facets; /* number of facets in facet_list
includes visble faces (num_visible) */
int num_vertices; /* number of vertices in facet_list */
int num_outside; /* number of points in outsidesets (for tracing and RANDOMoutside)
includes coplanar outsideset points for NARROWhull/qh_outcoplanar() */
int num_good; /* number of good facets (after findgood_all) */
unsigned facet_id; /* ID of next, new facet from newfacet() */
unsigned ridge_id:24; /* ID of next, new ridge from newridge() */
unsigned vertex_id:24; /* ID of next, new vertex from newvertex() */
/*----------------------------------
qh global variables
defines minimum and maximum distances, next visit ids, several flags,
and other global variables.
initialize in qh_initbuild or qh_maxmin if used in qh_buildhull
*/
unsigned long hulltime; /* ignore time to set up input and randomize */
/* use unsigned to avoid wrap-around errors */
boolT ALLOWrestart; /* true if qh_precision can use qh.restartexit */
int build_cnt; /* number of calls to qh_initbuild */
qh_CENTER CENTERtype; /* current type of facet->center, qh_CENTER */
int furthest_id; /* pointid of furthest point, for tracing */
facetT *GOODclosest; /* closest facet to GOODthreshold in qh_findgood */
boolT hasAreaVolume; /* true if totarea, totvol was defined by qh_getarea */
boolT hasTriangulation; /* true if triangulation created by qh_triangulate */
realT JOGGLEmax; /* set 'QJn' if randomly joggle input */
boolT maxoutdone; /* set qh_check_maxout(), cleared by qh_addpoint() */
realT max_outside; /* maximum distance from a point to a facet,
before roundoff, not simplicial vertices
actual outer plane is +DISTround and
computed outer plane is +2*DISTround */
realT max_vertex; /* maximum distance (>0) from vertex to a facet,
before roundoff, due to a merge */
realT min_vertex; /* minimum distance (<0) from vertex to a facet,
before roundoff, due to a merge
if qh.JOGGLEmax, qh_makenewplanes sets it
recomputed if qh.DOcheckmax, default -qh.DISTround */
boolT NEWfacets; /* true while visible facets invalid due to new or merge
from makecone/attachnewfacets to deletevisible */
boolT findbestnew; /* true if partitioning calls qh_findbestnew */
boolT findbest_notsharp; /* true if new facets are at least 90 degrees */
boolT NOerrexit; /* true if qh.errexit is not available */
realT PRINTcradius; /* radius for printing centrums */
realT PRINTradius; /* radius for printing vertex spheres and points */
boolT POSTmerging; /* true when post merging */
int printoutvar; /* temporary variable for qh_printbegin, etc. */
int printoutnum; /* number of facets printed */
boolT QHULLfinished; /* True after qhull() is finished */
realT totarea; /* 'FA': total facet area computed by qh_getarea, hasAreaVolume */
realT totvol; /* 'FA': total volume computed by qh_getarea, hasAreaVolume */
unsigned int visit_id; /* unique ID for searching neighborhoods, */
unsigned int vertex_visit:31; /* unique ID for searching vertices, reset with qh_buildtracing */
boolT ZEROall_ok; /* True if qh_checkzero always succeeds */
boolT WAScoplanar; /* True if qh_partitioncoplanar (qh_check_maxout) */
/*----------------------------------
qh global sets
defines sets for merging, initial simplex, hashing, extra input points,
and deleted vertices
*/
setT *facet_mergeset; /* temporary set of merges to be done */
setT *degen_mergeset; /* temporary set of degenerate and redundant merges */
setT *hash_table; /* hash table for matching ridges in qh_matchfacets
size is setsize() */
setT *other_points; /* additional points */
setT *del_vertices; /* vertices to partition and delete with visible
facets. Have deleted set for checkfacet */
/*----------------------------------
qh global buffers
defines buffers for maxtrix operations, input, and error messages
*/
coordT *gm_matrix; /* (dim+1)Xdim matrix for geom.c */
coordT **gm_row; /* array of gm_matrix rows */
char* line; /* malloc'd input line of maxline+1 chars */
int maxline;
coordT *half_space; /* malloc'd input array for halfspace (qh normal_size+coordT) */
coordT *temp_malloc; /* malloc'd input array for points */
/*----------------------------------
qh static variables
defines static variables for individual functions
notes:
do not use 'static' within a function. Multiple instances of qhull
may exist.
do not assume zero initialization, 'QPn' may cause a restart
*/
boolT ERREXITcalled; /* true during qh_errexit (prevents duplicate calls */
boolT firstcentrum; /* for qh_printcentrum */
boolT old_randomdist; /* save RANDOMdist flag during io, tracing, or statistics */
setT *coplanarfacetset; /* set of coplanar facets for searching qh_findbesthorizon() */
realT last_low; /* qh_scalelast parameters for qh_setdelaunay */
realT last_high;
realT last_newhigh;
unsigned lastreport; /* for qh_buildtracing */
int mergereport; /* for qh_tracemerging */
qhstatT *old_qhstat; /* for saving qh_qhstat in save_qhull() and UsingLibQhull. Free with qh_free() */
setT *old_tempstack; /* for saving qhmem.tempstack in save_qhull */
int ridgeoutnum; /* number of ridges for 4OFF output (qh_printbegin,etc) */
};
/*=========== -macros- =========================*/
/*----------------------------------
otherfacet_(ridge, facet)
return neighboring facet for a ridge in facet
*/
#define otherfacet_(ridge, facet) \
(((ridge)->top == (facet)) ? (ridge)->bottom : (ridge)->top)
/*----------------------------------
getid_(p)
return int ID for facet, ridge, or vertex
return -1 if NULL
*/
#define getid_(p) ((p) ? (int)((p)->id) : -1)
/*============== FORALL macros ===================*/
/*----------------------------------
FORALLfacets { ... }
assign 'facet' to each facet in qh.facet_list
notes:
uses 'facetT *facet;'
assumes last facet is a sentinel
see:
FORALLfacet_( facetlist )
*/
#define FORALLfacets for (facet=qh facet_list;facet && facet->next;facet=facet->next)
/*----------------------------------
FORALLpoints { ... }
assign 'point' to each point in qh.first_point, qh.num_points
declare:
coordT *point, *pointtemp;
*/
#define FORALLpoints FORALLpoint_(qh first_point, qh num_points)
/*----------------------------------
FORALLpoint_( points, num) { ... }
assign 'point' to each point in points array of num points
declare:
coordT *point, *pointtemp;
*/
#define FORALLpoint_(points, num) for (point= (points), \
pointtemp= (points)+qh hull_dim*(num); point < pointtemp; point += qh hull_dim)
/*----------------------------------
FORALLvertices { ... }
assign 'vertex' to each vertex in qh.vertex_list
declare:
vertexT *vertex;
notes:
assumes qh.vertex_list terminated with a sentinel
*/
#define FORALLvertices for (vertex=qh vertex_list;vertex && vertex->next;vertex= vertex->next)
/*----------------------------------
FOREACHfacet_( facets ) { ... }
assign 'facet' to each facet in facets
declare:
facetT *facet, **facetp;
see:
FOREACHsetelement_
*/
#define FOREACHfacet_(facets) FOREACHsetelement_(facetT, facets, facet)
/*----------------------------------
FOREACHneighbor_( facet ) { ... }
assign 'neighbor' to each neighbor in facet->neighbors
FOREACHneighbor_( vertex ) { ... }
assign 'neighbor' to each neighbor in vertex->neighbors
declare:
facetT *neighbor, **neighborp;
see:
FOREACHsetelement_
*/
#define FOREACHneighbor_(facet) FOREACHsetelement_(facetT, facet->neighbors, neighbor)
/*----------------------------------
FOREACHpoint_( points ) { ... }
assign 'point' to each point in points set
declare:
pointT *point, **pointp;
see:
FOREACHsetelement_
*/
#define FOREACHpoint_(points) FOREACHsetelement_(pointT, points, point)
/*----------------------------------
FOREACHridge_( ridges ) { ... }
assign 'ridge' to each ridge in ridges set
declare:
ridgeT *ridge, **ridgep;
see:
FOREACHsetelement_
*/
#define FOREACHridge_(ridges) FOREACHsetelement_(ridgeT, ridges, ridge)
/*----------------------------------
FOREACHvertex_( vertices ) { ... }
assign 'vertex' to each vertex in vertices set
declare:
vertexT *vertex, **vertexp;
see:
FOREACHsetelement_
*/
#define FOREACHvertex_(vertices) FOREACHsetelement_(vertexT, vertices,vertex)
/*----------------------------------
FOREACHfacet_i_( facets ) { ... }
assign 'facet' and 'facet_i' for each facet in facets set
declare:
facetT *facet;
int facet_n, facet_i;
see:
FOREACHsetelement_i_
*/
#define FOREACHfacet_i_(facets) FOREACHsetelement_i_(facetT, facets, facet)
/*----------------------------------
FOREACHneighbor_i_( facet ) { ... }
assign 'neighbor' and 'neighbor_i' for each neighbor in facet->neighbors
FOREACHneighbor_i_( vertex ) { ... }
assign 'neighbor' and 'neighbor_i' for each neighbor in vertex->neighbors
declare:
facetT *neighbor;
int neighbor_n, neighbor_i;
see:
FOREACHsetelement_i_
*/
#define FOREACHneighbor_i_(facet) FOREACHsetelement_i_(facetT, facet->neighbors, neighbor)
/*----------------------------------
FOREACHpoint_i_( points ) { ... }
assign 'point' and 'point_i' for each point in points set
declare:
pointT *point;
int point_n, point_i;
see:
FOREACHsetelement_i_
*/
#define FOREACHpoint_i_(points) FOREACHsetelement_i_(pointT, points, point)
/*----------------------------------
FOREACHridge_i_( ridges ) { ... }
assign 'ridge' and 'ridge_i' for each ridge in ridges set
declare:
ridgeT *ridge;
int ridge_n, ridge_i;
see:
FOREACHsetelement_i_
*/
#define FOREACHridge_i_(ridges) FOREACHsetelement_i_(ridgeT, ridges, ridge)
/*----------------------------------
FOREACHvertex_i_( vertices ) { ... }
assign 'vertex' and 'vertex_i' for each vertex in vertices set
declare:
vertexT *vertex;
int vertex_n, vertex_i;
see:
FOREACHsetelement_i_
*/
#define FOREACHvertex_i_(vertices) FOREACHsetelement_i_(vertexT, vertices,vertex)
/********* -libqhull.c prototypes (duplicated from qhull_a.h) **********************/
void qh_qhull(void);
boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist);
void qh_printsummary(FILE *fp);
/********* -user.c prototypes (alphabetical) **********************/
void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge);
void qh_errprint(const char* string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex);
int qh_new_qhull(int dim, int numpoints, coordT *points, boolT ismalloc,
char *qhull_cmd, FILE *outfile, FILE *errfile);
void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall);
void qh_printhelp_degenerate(FILE *fp);
void qh_printhelp_narrowhull(FILE *fp, realT minangle);
void qh_printhelp_singular(FILE *fp);
void qh_user_memsizes(void);
/********* -usermem.c prototypes (alphabetical) **********************/
void qh_exit(int exitcode);
void qh_free(void *mem);
void *qh_malloc(size_t size);
/********* -userprintf.c and userprintf_rbox.c prototypes **********************/
void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
void qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... );
/***** -geom.c/geom2.c/random.c prototypes (duplicated from geom.h, random.h) ****************/
facetT *qh_findbest(pointT *point, facetT *startfacet,
boolT bestoutside, boolT newfacets, boolT noupper,
realT *dist, boolT *isoutside, int *numpart);
facetT *qh_findbestnew(pointT *point, facetT *startfacet,
realT *dist, boolT bestoutside, boolT *isoutside, int *numpart);
boolT qh_gram_schmidt(int dim, realT **rows);
void qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane);
void qh_printsummary(FILE *fp);
void qh_projectinput(void);
void qh_randommatrix(realT *buffer, int dim, realT **row);
void qh_rotateinput(realT **rows);
void qh_scaleinput(void);
void qh_setdelaunay(int dim, int count, pointT *points);
coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible);
/***** -global.c prototypes (alphabetical) ***********************/
unsigned long qh_clock(void);
void qh_checkflags(char *command, char *hiddenflags);
void qh_clear_outputflags(void);
void qh_freebuffers(void);
void qh_freeqhull(boolT allmem);
void qh_freeqhull2(boolT allmem);
void qh_init_A(FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]);
void qh_init_B(coordT *points, int numpoints, int dim, boolT ismalloc);
void qh_init_qhull_command(int argc, char *argv[]);
void qh_initbuffers(coordT *points, int numpoints, int dim, boolT ismalloc);
void qh_initflags(char *command);
void qh_initqhull_buffers(void);
void qh_initqhull_globals(coordT *points, int numpoints, int dim, boolT ismalloc);
void qh_initqhull_mem(void);
void qh_initqhull_outputflags(void);
void qh_initqhull_start(FILE *infile, FILE *outfile, FILE *errfile);
void qh_initqhull_start2(FILE *infile, FILE *outfile, FILE *errfile);
void qh_initthresholds(char *command);
void qh_option(const char *option, int *i, realT *r);
#if qh_QHpointer
void qh_restore_qhull(qhT **oldqh);
qhT *qh_save_qhull(void);
#endif
/***** -io.c prototypes (duplicated from io.h) ***********************/
void qh_dfacet( unsigned id);
void qh_dvertex( unsigned id);
void qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall);
void qh_produce_output(void);
coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
/********* -mem.c prototypes (duplicated from mem.h) **********************/
void qh_meminit(FILE *ferr);
void qh_memfreeshort(int *curlong, int *totlong);
/********* -poly.c/poly2.c prototypes (duplicated from poly.h) **********************/
void qh_check_output(void);
void qh_check_points(void);
setT *qh_facetvertices(facetT *facetlist, setT *facets, boolT allfacets);
facetT *qh_findbestfacet(pointT *point, boolT bestoutside,
realT *bestdist, boolT *isoutside);
vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp);
pointT *qh_point(int id);
setT *qh_pointfacet(void /*qh.facet_list*/);
int qh_pointid(pointT *point);
setT *qh_pointvertex(void /*qh.facet_list*/);
void qh_setvoronoi_all(void);
void qh_triangulate(void /*qh.facet_list*/);
/********* -rboxpoints.c prototypes **********************/
int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command);
void qh_errexit_rbox(int exitcode);
/********* -stat.c prototypes (duplicated from stat.h) **********************/
void qh_collectstatistics(void);
void qh_printallstatistics(FILE *fp, const char *string);
#endif /* qhDEFlibqhull */
diff --git a/src/libqhull/qh-user.htm b/src/libqhull/qh-user.htm
index a8afed4..b917920 100644
--- a/src/libqhull/qh-user.htm
+++ b/src/libqhull/qh-user.htm
@@ -1,263 +1,265 @@
user.c -- user-definable operations
Up: Home page for Qhull
Up: Qhull manual: Table of Contents
Up: Programs
Options
Output
Formats
Geomview
Print
Qhull
Precision
Trace
Up: Qhull code: Table of Contents
To: Qhull functions, macros, and data structures
To: Geom Global
Io Mem
Merge Poly
Qhull Set
Stat User
user.c -- user-definable operations
This section contains functions and constants that the
user may want to change.
Copyright © 1995-2012 C.B. Barber
» Geom
Global
Io Mem
Merge Poly
Qhull Set
Stat User
- qh_DEFAULTbox
define default box size for rbox, 'Qbb', and 'QbB' (Geomview expects 0.5)
- qh_INFINITE on
output, indicates Voronoi center at infinity
- qh_ORIENTclock
define convention for orienting facets
- qh_ZEROdelaunay
define facets that are ignored in Delaunay triangulations
- qh_exit exit program, same as exit().
- qh_free free memory, same as free().
- qh_malloc allocate memory, same as malloc()
- qh_fprintf print
information from Qhull, sames as fprintf().
- qh_fprintf_rbox print
information from Rbox, sames as fprintf().
Up:
Home page for
Qhull
Up: Qhull manual: Table of Contents
Up: Programs
Options
Output
Formats
Geomview
Print
Qhull
Precision
Trace
Up: Qhull code: Table of Contents
To: Qhull functions, macros, and data structures
To: Geom
Global Io
Mem Merge
Poly Qhull
Set Stat
User
The
Geometry Center Home Page
Comments to: qhull@qhull.org
Created: May 2, 1997 --- Last modified: see top
diff --git a/src/libqhull/rboxlib.c b/src/libqhull/rboxlib.c
index 8eecdd6..d6eea41 100644
--- a/src/libqhull/rboxlib.c
+++ b/src/libqhull/rboxlib.c
@@ -1,795 +1,799 @@
/* ---------------------------------
rboxlib.c
Generate input points
notes:
For documentation, see prompt[] of rbox.c
50 points generated for 'rbox D4'
WARNING:
incorrect range if qh_RANDOMmax is defined wrong (user.h)
*/
#include "random.h"
#include "libqhull.h"
#include
#include
#include
#include
#include
#include
#include
#include
#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( double a);
void qh_out1( double a);
void qh_out2n( double a, double b);
void qh_out3n( double a, double b, double c);
void qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... );
void qh_free(void *mem);
void *qh_malloc(size_t size);
int qh_rand( void);
void qh_srand( int seed);
/* ------------------------------ globals -------------------*/
/* No state is carried between rbox requests */
typedef struct rboxT rboxT;
struct rboxT {
FILE *fout;
FILE *ferr;
int isinteger;
double out_offset;
jmp_buf errexit; /* exit label for rboxpoints, defined by setjmp(), called by qh_errexit_rbox() */
+ char jmpXtra[40]; /* extra bytes in case jmp_buf is defined wrong by compiler */
};
int rbox_inuse= 0;
rboxT rbox;
/*---------------------------------
qh_rboxpoints( fout, ferr, rbox_command )
Generate points to fout according to rbox options
Report errors on 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 stdio, redefine qh_malloc, qh_free, and qh_fprintf_rbox (user.c)
Rbox is not multithreaded.
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(FILE* fout, FILE* ferr, char* rbox_command) {
int i,j,k;
int gendim;
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;
double coord[MAXdim], offset, meshm=3.0, meshn=4.0, meshr=5.0;
double *simplex= NULL, *simplexp;
int nthroot, mult[MAXdim];
double norm, factor, randr, rangap, 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[200], seedbuf[200];
char *s= command, *t, *first_point= NULL;
time_t timedata;
int exitcode;
if (rbox_inuse) {
qh_fprintf_rbox(rbox.ferr, 6188, "rbox error: rbox in use by another process. Please lock calls to rbox.\n");
return qh_ERRqhull;
}
rbox_inuse= True;
rbox.ferr= ferr;
rbox.fout= fout;
exitcode= setjmp(rbox.errexit);
if (exitcode) {
/* same code for error exit and normal return */
if (simplex)
qh_free(simplex);
rbox_inuse= False;
return exitcode;
}
*command= '\0';
strncat(command, rbox_command, sizeof(command)-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':
rbox.isinteger= 1;
break;
case 'B':
box= qh_strtod(s, &s);
isbox= 1;
break;
case 'D':
dim= qh_strtol(s, &s);
if (dim < 1
|| dim > MAXdim) {
qh_fprintf_rbox(rbox.ferr, 6189, "rbox error: dimension, D%d, out of bounds (>=%d or <=0)", dim, MAXdim);
qh_errexit_rbox(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(rbox.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':
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(rbox.ferr, 7070, "rbox error: unknown flag at %s.\nExecute 'rbox' without arguments for documentation.\n", s);
qh_errexit_rbox(qh_ERRinput);
}
if (*s && !isspace(*s)) {
qh_fprintf_rbox(rbox.ferr, 7071, "rbox error: missing space between flags at %s.\n", s);
qh_errexit_rbox(qh_ERRinput);
}
}
/* ============= defaults, constants, and sizes =============== */
if (rbox.isinteger && !isbox)
box= qh_DEFAULTzbox;
if (addcube) {
cubesize= (int)floor(ldexp(1.0,dim)+0.5);
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(rbox.ferr, 6190, "rbox error: can not combine 'Ln' with 'Zn'\n");
qh_errexit_rbox(qh_ERRinput);
}
if (radius <= 1.0) {
qh_fprintf_rbox(rbox.ferr, 6191, "rbox error: lens radius %.2g should be greater than 1.0\n",
radius);
qh_errexit_rbox(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(rbox.ferr, 6192, "rbox error: missing count\n");
qh_errexit_rbox(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(rbox.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_ERRinput);
}
/* ============= 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;
/* ============= 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);
sprintf(seedbuf, " 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_(seed);
/* ============= print header =============== */
if (iscdd)
qh_fprintf_rbox(rbox.fout, 9391, "%s\nbegin\n %d %d %s\n",
NOcommand ? "" : command,
totpoints, dim+1,
rbox.isinteger ? "integer" : "real");
else if (NOcommand)
qh_fprintf_rbox(rbox.fout, 9392, "%d\n%d\n", dim, totpoints);
else
qh_fprintf_rbox(rbox.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( 1.0);
while (*++s) {
qh_out1( qh_strtod(s, &s));
count++;
if (isspace(*s) || !*s)
break;
if (*s != ',') {
qh_fprintf_rbox(rbox.ferr, 6194, "rbox error: missing comma after coordinate in %s\n\n", s);
qh_errexit_rbox(qh_ERRinput);
}
}
if (count < dim) {
for (k=dim-count; k--; )
qh_out1( 0.0);
}else if (count > dim) {
qh_fprintf_rbox(rbox.ferr, 6195, "rbox error: %d coordinates instead of %d coordinates in %s\n\n",
count, dim, s);
qh_errexit_rbox(qh_ERRinput);
}
qh_fprintf_rbox(rbox.fout, 9394, "\n");
while ((s= strchr(s, 'P'))) {
if (isspace(s[-1]))
break;
}
}
}
/* ============= simplex distribution =============== */
if (issimplex+issimplex2) {
if (!(simplex= (double*)qh_malloc( dim * (dim+1) * sizeof(double)))) {
qh_fprintf_rbox(rbox.ferr, 6196, "rbox error: insufficient memory for simplex\n");
qh_errexit_rbox(qh_ERRmem); /* qh_ERRmem */
}
simplexp= simplex;
if (isregular) {
for (i=0; i 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;
}
/* ============= write point =============== */
if (iscdd)
qh_out1( 1.0);
for (k=0; k < dim; k++)
qh_out1( coord[k] * box);
qh_fprintf_rbox(rbox.fout, 9399, "\n");
}
}
/* ============= write cube vertices =============== */
if (addcube) {
for (j=0; j=0; k--) {
if (j & ( 1 << k))
qh_out1( cube);
else
qh_out1( -cube);
}
qh_fprintf_rbox(rbox.fout, 9400, "\n");
}
}
/* ============= write diamond vertices =============== */
if (adddiamond) {
for (j=0; j=0; k--) {
if (j/2 != k)
qh_out1( 0.0);
else if (j & 0x1)
qh_out1( diamond);
else
qh_out1( -diamond);
}
qh_fprintf_rbox(rbox.fout, 9401, "\n");
}
}
if (iscdd)
qh_fprintf_rbox(rbox.fout, 9402, "end\nhull\n");
/* same code for error exit and normal return */
if (simplex)
qh_free(simplex);
rbox_inuse= False;
return qh_ERRnone;
} /* rboxpoints */
/*------------------------------------------------
outxxx - output functions
*/
int qh_roundi( double a) {
if (a < 0.0) {
if (a - 0.5 < INT_MIN) {
qh_fprintf_rbox(rbox.ferr, 6200, "rbox input error: negative coordinate %2.2g is too large. Reduce 'Bn'\n", a);
qh_errexit_rbox(qh_ERRinput);
}
return (int)(a - 0.5);
}else {
if (a + 0.5 > INT_MAX) {
qh_fprintf_rbox(rbox.ferr, 6201, "rbox input error: coordinate %2.2g is too large. Reduce 'Bn'\n", a);
qh_errexit_rbox(qh_ERRinput);
}
return (int)(a + 0.5);
}
} /* qh_roundi */
void qh_out1(double a) {
if (rbox.isinteger)
qh_fprintf_rbox(rbox.fout, 9403, "%d ", qh_roundi( a+rbox.out_offset));
else
qh_fprintf_rbox(rbox.fout, 9404, qh_REAL_1, a+rbox.out_offset);
} /* qh_out1 */
void qh_out2n( double a, double b) {
if (rbox.isinteger)
qh_fprintf_rbox(rbox.fout, 9405, "%d %d\n", qh_roundi(a+rbox.out_offset), qh_roundi(b+rbox.out_offset));
else
qh_fprintf_rbox(rbox.fout, 9406, qh_REAL_2n, a+rbox.out_offset, b+rbox.out_offset);
} /* qh_out2n */
void qh_out3n( double a, double b, double c) {
if (rbox.isinteger)
qh_fprintf_rbox(rbox.fout, 9407, "%d %d %d\n", qh_roundi(a+rbox.out_offset), qh_roundi(b+rbox.out_offset), qh_roundi(c+rbox.out_offset));
else
qh_fprintf_rbox(rbox.fout, 9408, qh_REAL_3n, a+rbox.out_offset, b+rbox.out_offset, c+rbox.out_offset);
} /* qh_out3n */
+/*------------------------------------------------
+ Only called from qh_rboxpoints or qh_fprintf_rbox (which is only called from qh_rboxpoints)
+*/
void qh_errexit_rbox(int exitcode)
{
longjmp(rbox.errexit, exitcode);
} /* rbox_errexit */
diff --git a/src/libqhull/user.c b/src/libqhull/user.c
index 653c5a4..7249843 100644
--- a/src/libqhull/user.c
+++ b/src/libqhull/user.c
@@ -1,527 +1,528 @@
/* ---------------------------------
user.c
user redefinable functions
see user2.c for qh_fprintf, qh_malloc, qh_free
see README.txt see COPYING.txt for copyright information.
see libqhull.h for data structures, macros, and user-callable functions.
see user_eg.c, unix.c, and qhull_interface.cpp for examples.
see user.h for user-definable constants
use qh_NOmem in mem.h to turn off memory management
use qh_NOmerge in user.h to turn off facet merging
set qh_KEEPstatistics in user.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
call_qhull 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.c for an
example. We recommend keeping io.o for the extra debugging
information it supplies.
*/
#include "qhull_a.h"
#include
/*---------------------------------
qh_call_qhull( void )
template for calling qhull from inside your program
remove #if 0, #endif to compile
returns:
exit code(see qh_ERR... in libqhull.h)
all memory freed
notes:
This can be called any number of times.
see:
qh_call_qhull_once()
*/
#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 qh_opt.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 */
#if qh_QHpointer /* see user.h */
if (qh_qh){
printf ("QH6238: Qhull link error. The global variable qh_qh was not initialized\n\
to NULL by global.c. Please compile this program with -Dqh_QHpointer_dllimport\n\
as well as -Dqh_QHpointer, or use libqhullstatic, or use a different tool chain.\n\n");
exit -1;
}
#endif
/* initialize dim, numpoints, points[], ismalloc here */
exitcode= qh_new_qhull(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_ALL);
qh_memfreeshort(&curlong, &totlong);
if (curlong || totlong)
qh_fprintf(errfile, 7068, "qhull internal warning (main): did not free %d bytes of long memory(%d pieces)\n", totlong, curlong);
}
#endif
/*---------------------------------
qh_new_qhull( dim, numpoints, points, ismalloc, qhull_cmd, outfile, errfile )
build new qhull data structure and return 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().
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')
To allow multiple, concurrent calls to qhull()
- set qh_QHpointer in user.h
- use qh_save_qhull and qh_restore_qhull to swap the global data structure between calls.
- use qh_freeqhull(qh_ALL) to free intermediate convex hulls
see:
user_eg.c for an example
*/
int qh_new_qhull(int dim, int numpoints, coordT *points, boolT ismalloc,
char *qhull_cmd, FILE *outfile, FILE *errfile) {
int exitcode, hulldim;
boolT new_ismalloc;
static boolT firstcall = True;
coordT *new_points;
if (firstcall) {
qh_meminit(errfile);
firstcall= False;
}
if (strncmp(qhull_cmd,"qhull ", (size_t)6)) {
qh_fprintf(errfile, 6186, "qhull error (qh_new_qhull): start qhull_cmd argument with \"qhull \"\n");
qh_exit(qh_ERRinput);
}
qh_initqhull_start(NULL, outfile, errfile);
trace1((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(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(hulldim);
new_points= qh_sethalfspace_all(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(new_points, numpoints, hulldim, new_ismalloc);
qh_qhull();
qh_check_output();
if (outfile) {
qh_produce_output();
}else {
qh_prepare_output();
}
if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
qh_check_points();
}
qh NOerrexit = True;
return exitcode;
} /* new_qhull */
/*---------------------------------
qh_errexit( 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.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(int exitcode, facetT *facet, ridgeT *ridge) {
if (qh ERREXITcalled) {
qh_fprintf(qh ferr, 8126, "\nqhull error while processing previous error. Exit program\n");
qh_exit(qh_ERRqhull);
}
qh ERREXITcalled= True;
if (!qh QHULLfinished)
qh hulltime= qh_CPUclock - qh hulltime;
qh_errprint("ERRONEOUS", facet, NULL, ridge, NULL);
qh_fprintf(qh ferr, 8127, "\nWhile executing: %s | %s\n", qh rbox_command, qh qhull_command);
qh_fprintf(qh ferr, 8128, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
if (qh furthest_id >= 0) {
qh_fprintf(qh ferr, 8129, "Last point added to hull was p%d.", qh furthest_id);
if (zzval_(Ztotmerge))
qh_fprintf(qh ferr, 8130, " Last merge was #%d.", zzval_(Ztotmerge));
if (qh QHULLfinished)
qh_fprintf(qh ferr, 8131, "\nQhull has finished constructing the hull.");
else if (qh POSTmerging)
qh_fprintf(qh ferr, 8132, "\nQhull has started post-merging.");
qh_fprintf(qh ferr, 8133, "\n");
}
if (qh FORCEoutput && (qh QHULLfinished || (!facet && !ridge)))
qh_produce_output();
else if (exitcode != qh_ERRinput) {
if (exitcode != qh_ERRsingular && zzval_(Zsetplane) > qh hull_dim+1) {
qh_fprintf(qh ferr, 8134, "\nAt error exit:\n");
qh_printsummary(qh ferr);
if (qh PRINTstatistics) {
qh_collectstatistics();
qh_printstatistics(qh ferr, "at error exit");
qh_memstatistics(qh ferr);
}
}
if (qh PRINTprecision)
qh_printstats(qh ferr, qhstat precision, NULL);
}
if (!exitcode)
exitcode= qh_ERRqhull;
else if (exitcode == qh_ERRsingular)
qh_printhelp_singular(qh ferr);
else if (exitcode == qh_ERRprec && !qh PREmerge)
qh_printhelp_degenerate(qh ferr);
if (qh NOerrexit) {
qh_fprintf(qh ferr, 6187, "qhull error while ending program. Exit program\n");
qh_exit(qh_ERRqhull);
}
qh ERREXITcalled= False;
qh NOerrexit= True;
+ qh->ALLOWrestart= False; /* longjmp will undo qh_build_withrestart */
longjmp(qh errexit, exitcode);
} /* errexit */
/*---------------------------------
qh_errprint( 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(const char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
int i;
if (atfacet) {
qh_fprintf(qh ferr, 8135, "%s FACET:\n", string);
qh_printfacet(qh ferr, atfacet);
}
if (otherfacet) {
qh_fprintf(qh ferr, 8136, "%s OTHER FACET:\n", string);
qh_printfacet(qh ferr, otherfacet);
}
if (atridge) {
qh_fprintf(qh ferr, 8137, "%s RIDGE:\n", string);
qh_printridge(qh ferr, atridge);
if (atridge->top && atridge->top != atfacet && atridge->top != otherfacet)
qh_printfacet(qh ferr, atridge->top);
if (atridge->bottom
&& atridge->bottom != atfacet && atridge->bottom != otherfacet)
qh_printfacet(qh ferr, atridge->bottom);
if (!atfacet)
atfacet= atridge->top;
if (!otherfacet)
otherfacet= otherfacet_(atridge, atfacet);
}
if (atvertex) {
qh_fprintf(qh ferr, 8138, "%s VERTEX:\n", string);
qh_printvertex(qh ferr, atvertex);
}
if (qh fout && qh FORCEoutput && atfacet && !qh QHULLfinished && !qh IStracing) {
qh_fprintf(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 fout, qh PRINTout[i], atfacet, otherfacet,
!qh_ALL);
}
} /* errprint */
/*---------------------------------
qh_printfacetlist( 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(facetT *facetlist, setT *facets, boolT printall) {
facetT *facet, **facetp;
qh_printbegin(qh ferr, qh_PRINTfacets, facetlist, facets, printall);
FORALLfacet_(facetlist)
qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
FOREACHfacet_(facets)
qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
qh_printend(qh ferr, qh_PRINTfacets, facetlist, facets, printall);
} /* printfacetlist */
/*---------------------------------
qh_printhelp_degenerate( fp )
prints descriptive message for precision error
notes:
no message if qh_QUICKhelp
*/
void qh_printhelp_degenerate(FILE *fp) {
if (qh MERGEexact || qh PREmerge || qh JOGGLEmax < REALmax/2)
qh_fprintf(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(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(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.h).\n");
#endif
if (qh DELAUNAY && !qh SCALElast && qh MAXabs_coord > 1e4)
qh_fprintf(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(fp, 9372, "\
When computing the Delaunay triangulation:\n\
- use 'Qz' to add a point at-infinity. This reduces precision problems.\n");
qh_fprintf(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(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 */
/*---------------------------------
qh_printhelp_narrowhull( minangle )
Warn about a narrow hull
notes:
Alternatively, reduce qh_WARNnarrow in user.h
*/
void qh_printhelp_narrowhull(FILE *fp, realT minangle) {
qh_fprintf(fp, 9375, "qhull precision warning: \n\
The initial hull is narrow (cosine of min. angle is %.16f).\n\
Is the input lower dimensional (e.g., on a plane in 3-d)? Qhull may\n\
produce a wide facet. Options 'QbB' (scale to unit box) or 'Qbb' (scale\n\
last coordinate) may remove this warning. Use 'Pp' to skip this warning.\n\
See 'Limitations' in qh-impre.htm.\n",
-minangle); /* convert from angle between normals to angle between facets */
} /* printhelp_narrowhull */
/*---------------------------------
qh_printhelp_singular( fp )
prints descriptive message for singular input
*/
void qh_printhelp_singular(FILE *fp) {
facetT *facet;
vertexT *vertex, **vertexp;
realT min, max, *coord, dist;
int i,k;
qh_fprintf(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(fp, "", qh facet_list, NULL, qh_ALL);
if (!qh_QUICKhelp)
qh_fprintf(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(fp, "center point", qh hull_dim, qh interior_point, -1);
qh_fprintf(fp, 9378, "\n");
FORALLfacets {
qh_fprintf(fp, 9379, "facet");
FOREACHvertex_(facet->vertices)
qh_fprintf(fp, 9380, " p%d", qh_pointid(vertex->point));
zinc_(Zdistio);
qh_distplane(qh interior_point, facet, &dist);
qh_fprintf(fp, 9381, " distance= %4.2g\n", dist);
}
if (!qh_QUICKhelp) {
if (qh HALFspace)
qh_fprintf(fp, 9382, "\n\
These points are the dual of the given halfspaces. They indicate that\n\
the intersection is degenerate.\n");
qh_fprintf(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(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(fp, 9385, "\nThe min and max coordinates for each dimension are:\n");
for (k=0; k < qh hull_dim; k++) {
min= REALmax;
max= -REALmin;
for (i=qh num_points, coord= qh first_point+k; i--; coord += qh hull_dim) {
maximize_(max, *coord);
minimize_(min, *coord);
}
qh_fprintf(fp, 9386, " %d: %8.4g %8.4g difference= %4.4g\n", k, min, max, max-min);
}
if (!qh_QUICKhelp) {
qh_fprintf(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(fp, 9388, "\
- recompile qhull for realT precision(#define REALfloat 0 in libqhull.h).\n");
#endif
qh_fprintf(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 */
/*---------------------------------
qh_user_memsizes()
allocate up to 10 additional, quick allocation sizes
notes:
increase maximum number of allocations in qh_initqhull_mem()
*/
void qh_user_memsizes(void) {
/* qh_memsize(size); */
} /* user_memsizes */
diff --git a/src/libqhull/user.h b/src/libqhull/user.h
index b0f57b1..0a162e2 100644
--- a/src/libqhull/user.h
+++ b/src/libqhull/user.h
@@ -1,858 +1,859 @@
/* ---------------------------------
user.h
user redefinable constants
see qh-user.htm. see COPYING for copyright information.
before reading any code, review libqhull.h for data structure definitions and
the "qh" macro.
Sections:
============= qhull library constants ======================
============= data types and configuration macros ==========
============= performance related constants ================
============= memory constants =============================
============= joggle constants =============================
============= conditional compilation ======================
============= -merge constants- ============================
Code flags --
NOerrors -- the code does not call qh_errexit()
WARN64 -- the code may be incompatible with 64-bit pointers
*/
#include
#ifndef qhDEFuser
#define qhDEFuser 1
/*============================================================*/
/*============= qhull library constants ======================*/
/*============================================================*/
/*----------------------------------
FILENAMElen -- max length for TI and TO filenames
*/
#define qh_FILENAMElen 500
/*----------------------------------
msgcode -- Unique message codes for qh_fprintf
If add new messages, assign these values and increment in user.h and user_r.h
+ See QhullError.h for 10000 errors.
def counters = [27, 1047, 2059, 3025, 4068, 5003,
6243, 7079, 8143, 9410, 10000, 11026]
See: qh_ERR* [libqhull.h]
*/
#define MSG_TRACE0 0
#define MSG_TRACE1 1000
#define MSG_TRACE2 2000
#define MSG_TRACE3 3000
#define MSG_TRACE4 4000
#define MSG_TRACE5 5000
#define MSG_ERROR 6000 /* errors written to qh.ferr */
#define MSG_WARNING 7000
#define MSG_STDERR 8000 /* log messages Written to qh.ferr */
#define MSG_OUTPUT 9000
-#define MSG_QHULL_ERROR 10000 /* errors thrown by QhullError [QhullError.h] */
+#define MSG_QHULL_ERROR 10000 /* errors thrown by QhullError.cpp */
#define MSG_FIXUP 11000 /* FIXUP QH11... */
#define MSG_MAXLEN 3000 /* qh_printhelp_degenerate() in user.c */
/*----------------------------------
qh_OPTIONline -- max length of an option line 'FO'
*/
#define qh_OPTIONline 80
/*============================================================*/
/*============= data types and configuration macros ==========*/
/*============================================================*/
/*----------------------------------
realT
set the size of floating point numbers
qh_REALdigits
maximimum number of significant digits
qh_REAL_1, qh_REAL_2n, qh_REAL_3n
format strings for printf
qh_REALmax, qh_REALmin
maximum and minimum (near zero) values
qh_REALepsilon
machine roundoff. Maximum roundoff error for addition and multiplication.
notes:
Select whether to store floating point numbers in single precision (float)
or double precision (double).
Use 'float' to save about 8% in time and 25% in space. This is particularly
helpful if high-d where convex hulls are space limited. Using 'float' also
reduces the printed size of Qhull's output since numbers have 8 digits of
precision.
Use 'double' when greater arithmetic precision is needed. This is needed
for Delaunay triangulations and Voronoi diagrams when you are not merging
facets.
If 'double' gives insufficient precision, your data probably includes
degeneracies. If so you should use facet merging (done by default)
or exact arithmetic (see imprecision section of manual, qh-impre.htm).
You may also use option 'Po' to force output despite precision errors.
You may use 'long double', but many format statements need to be changed
and you may need a 'long double' square root routine. S. Grundmann
(sg@eeiwzb.et.tu-dresden.de) has done this. He reports that the code runs
much slower with little gain in precision.
WARNING: on some machines, int f(){realT a= REALmax;return (a == REALmax);}
returns False. Use (a > REALmax/2) instead of (a == REALmax).
REALfloat = 1 all numbers are 'float' type
= 0 all numbers are 'double' type
*/
#define REALfloat 0
#if (REALfloat == 1)
#define realT float
#define REALmax FLT_MAX
#define REALmin FLT_MIN
#define REALepsilon FLT_EPSILON
#define qh_REALdigits 8 /* maximum number of significant digits */
#define qh_REAL_1 "%6.8g "
#define qh_REAL_2n "%6.8g %6.8g\n"
#define qh_REAL_3n "%6.8g %6.8g %6.8g\n"
#elif (REALfloat == 0)
#define realT double
#define REALmax DBL_MAX
#define REALmin DBL_MIN
#define REALepsilon DBL_EPSILON
#define qh_REALdigits 16 /* maximum number of significant digits */
#define qh_REAL_1 "%6.16g "
#define qh_REAL_2n "%6.16g %6.16g\n"
#define qh_REAL_3n "%6.16g %6.16g %6.16g\n"
#else
#error unknown float option
#endif
/*----------------------------------
qh_CPUclock
define the clock() function for reporting the total time spent by Qhull
returns CPU ticks as a 'long int'
qh_CPUclock is only used for reporting the total time spent by Qhull
qh_SECticks
the number of clock ticks per second
notes:
looks for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or assumes microseconds
to define a custom clock, set qh_CLOCKtype to 0
if your system does not use clock() to return CPU ticks, replace
qh_CPUclock with the corresponding function. It is converted
to 'unsigned long' to prevent wrap-around during long runs. By default,
defines clock_t as 'long'
Set qh_CLOCKtype to
1 for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or microsecond
Note: may fail if more than 1 hour elapsed time
2 use qh_clock() with POSIX times() (see global.c)
*/
#define qh_CLOCKtype 1 /* change to the desired number */
#if (qh_CLOCKtype == 1)
#if defined(CLOCKS_PER_SECOND)
#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
#define qh_SECticks CLOCKS_PER_SECOND
#elif defined(CLOCKS_PER_SEC)
#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
#define qh_SECticks CLOCKS_PER_SEC
#elif defined(CLK_TCK)
#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
#define qh_SECticks CLK_TCK
#else
#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
#define qh_SECticks 1E6
#endif
#elif (qh_CLOCKtype == 2)
#define qh_CPUclock qh_clock() /* return CPU clock */
#define qh_SECticks 100
#else /* qh_CLOCKtype == ? */
#error unknown clock option
#endif
/*----------------------------------
qh_RANDOMtype, qh_RANDOMmax, qh_RANDOMseed
define random number generator
qh_RANDOMint generates a random integer between 0 and qh_RANDOMmax.
qh_RANDOMseed sets the random number seed for qh_RANDOMint
Set qh_RANDOMtype (default 5) to:
1 for random() with 31 bits (UCB)
2 for rand() with RAND_MAX or 15 bits (system 5)
3 for rand() with 31 bits (Sun)
4 for lrand48() with 31 bits (Solaris)
5 for qh_rand() with 31 bits (included with Qhull)
notes:
Random numbers are used by rbox to generate point sets. Random
numbers are used by Qhull to rotate the input ('QRn' option),
simulate a randomized algorithm ('Qr' option), and to simulate
roundoff errors ('Rn' option).
Random number generators differ between systems. Most systems provide
rand() but the period varies. The period of rand() is not critical
since qhull does not normally use random numbers.
The default generator is Park & Miller's minimal standard random
number generator [CACM 31:1195 '88]. It is included with Qhull.
If qh_RANDOMmax is wrong, qhull will report a warning and Geomview
output will likely be invisible.
*/
#define qh_RANDOMtype 5 /* *** change to the desired number *** */
#if (qh_RANDOMtype == 1)
#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, random()/MAX */
#define qh_RANDOMint random()
#define qh_RANDOMseed_(seed) srandom(seed);
#elif (qh_RANDOMtype == 2)
#ifdef RAND_MAX
#define qh_RANDOMmax ((realT)RAND_MAX)
#else
#define qh_RANDOMmax ((realT)32767) /* 15 bits (System 5) */
#endif
#define qh_RANDOMint rand()
#define qh_RANDOMseed_(seed) srand((unsigned)seed);
#elif (qh_RANDOMtype == 3)
#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, Sun */
#define qh_RANDOMint rand()
#define qh_RANDOMseed_(seed) srand((unsigned)seed);
#elif (qh_RANDOMtype == 4)
#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, lrand38()/MAX */
#define qh_RANDOMint lrand48()
#define qh_RANDOMseed_(seed) srand48(seed);
#elif (qh_RANDOMtype == 5)
#define qh_RANDOMmax ((realT)2147483646UL) /* 31 bits, qh_rand/MAX */
#define qh_RANDOMint qh_rand()
#define qh_RANDOMseed_(seed) qh_srand(seed);
/* unlike rand(), never returns 0 */
#else
#error: unknown random option
#endif
/*----------------------------------
qh_ORIENTclock
0 for inward pointing normals by Geomview convention
*/
#define qh_ORIENTclock 0
/*============================================================*/
/*============= joggle constants =============================*/
/*============================================================*/
/*----------------------------------
qh_JOGGLEdefault
default qh.JOGGLEmax is qh.DISTround * qh_JOGGLEdefault
notes:
rbox s r 100 | qhull QJ1e-15 QR0 generates 90% faults at distround 7e-16
rbox s r 100 | qhull QJ1e-14 QR0 generates 70% faults
rbox s r 100 | qhull QJ1e-13 QR0 generates 35% faults
rbox s r 100 | qhull QJ1e-12 QR0 generates 8% faults
rbox s r 100 | qhull QJ1e-11 QR0 generates 1% faults
rbox s r 100 | qhull QJ1e-10 QR0 generates 0% faults
rbox 1000 W0 | qhull QJ1e-12 QR0 generates 86% faults
rbox 1000 W0 | qhull QJ1e-11 QR0 generates 20% faults
rbox 1000 W0 | qhull QJ1e-10 QR0 generates 2% faults
the later have about 20 points per facet, each of which may interfere
pick a value large enough to avoid retries on most inputs
*/
#define qh_JOGGLEdefault 30000.0
/*----------------------------------
qh_JOGGLEincrease
factor to increase qh.JOGGLEmax on qh_JOGGLEretry or qh_JOGGLEagain
*/
#define qh_JOGGLEincrease 10.0
/*----------------------------------
qh_JOGGLEretry
if ZZretry = qh_JOGGLEretry, increase qh.JOGGLEmax
notes:
try twice at the original value in case of bad luck the first time
*/
#define qh_JOGGLEretry 2
/*----------------------------------
qh_JOGGLEagain
every following qh_JOGGLEagain, increase qh.JOGGLEmax
notes:
1 is OK since it's already failed qh_JOGGLEretry times
*/
#define qh_JOGGLEagain 1
/*----------------------------------
qh_JOGGLEmaxincrease
maximum qh.JOGGLEmax due to qh_JOGGLEincrease
relative to qh.MAXwidth
notes:
qh.joggleinput will retry at this value until qh_JOGGLEmaxretry
*/
#define qh_JOGGLEmaxincrease 1e-2
/*----------------------------------
qh_JOGGLEmaxretry
stop after qh_JOGGLEmaxretry attempts
*/
#define qh_JOGGLEmaxretry 100
/*============================================================*/
/*============= performance related constants ================*/
/*============================================================*/
/*----------------------------------
qh_HASHfactor
total hash slots / used hash slots. Must be at least 1.1.
notes:
=2 for at worst 50% occupancy for qh hash_table and normally 25% occupancy
*/
#define qh_HASHfactor 2
/*----------------------------------
qh_VERIFYdirect
with 'Tv' verify all points against all facets if op count is smaller
notes:
if greater, calls qh_check_bestdist() instead
*/
#define qh_VERIFYdirect 1000000
/*----------------------------------
qh_INITIALsearch
if qh_INITIALmax, search points up to this dimension
*/
#define qh_INITIALsearch 6
/*----------------------------------
qh_INITIALmax
if dim >= qh_INITIALmax, use min/max coordinate points for initial simplex
notes:
from points with non-zero determinants
use option 'Qs' to override (much slower)
*/
#define qh_INITIALmax 8
/*============================================================*/
/*============= memory constants =============================*/
/*============================================================*/
/*----------------------------------
qh_MEMalign
memory alignment for qh_meminitbuffers() in global.c
notes:
to avoid bus errors, memory allocation must consider alignment requirements.
malloc() automatically takes care of alignment. Since mem.c manages
its own memory, we need to explicitly specify alignment in
qh_meminitbuffers().
A safe choice is sizeof(double). sizeof(float) may be used if doubles
do not occur in data structures and pointers are the same size. Be careful
of machines (e.g., DEC Alpha) with large pointers.
If using gcc, best alignment is [fmax_() is defined in geom_r.h]
#define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *))
*/
#define qh_MEMalign ((int)(fmax_(sizeof(realT), sizeof(void *))))
/*----------------------------------
qh_MEMbufsize
size of additional memory buffers
notes:
used for qh_meminitbuffers() in global.c
*/
#define qh_MEMbufsize 0x10000 /* allocate 64K memory buffers */
/*----------------------------------
qh_MEMinitbuf
size of initial memory buffer
notes:
use for qh_meminitbuffers() in global.c
*/
#define qh_MEMinitbuf 0x20000 /* initially allocate 128K buffer */
/*----------------------------------
qh_INFINITE
on output, indicates Voronoi center at infinity
*/
#define qh_INFINITE -10.101
/*----------------------------------
qh_DEFAULTbox
default box size (Geomview expects 0.5)
qh_DEFAULTbox
default box size for integer coorindate (rbox only)
*/
#define qh_DEFAULTbox 0.5
#define qh_DEFAULTzbox 1e6
/*============================================================*/
/*============= conditional compilation ======================*/
/*============================================================*/
/*----------------------------------
__cplusplus
defined by C++ compilers
__MSC_VER
defined by Microsoft Visual C++
__MWERKS__ && __POWERPC__
defined by Metrowerks when compiling for the Power Macintosh
__STDC__
defined for strict ANSI C
*/
/*----------------------------------
qh_COMPUTEfurthest
compute furthest distance to an outside point instead of storing it with the facet
=1 to compute furthest
notes:
computing furthest saves memory but costs time
about 40% more distance tests for partitioning
removes facet->furthestdist
*/
#define qh_COMPUTEfurthest 0
/*----------------------------------
qh_KEEPstatistics
=0 removes most of statistic gathering and reporting
notes:
if 0, code size is reduced by about 4%.
*/
#define qh_KEEPstatistics 1
/*----------------------------------
qh_MAXoutside
record outer plane for each facet
=1 to record facet->maxoutside
notes:
this takes a realT per facet and slightly slows down qhull
it produces better outer planes for geomview output
*/
#define qh_MAXoutside 1
/*----------------------------------
qh_NOmerge
disables facet merging if defined
notes:
This saves about 10% space.
Unless 'Q0'
qh_NOmerge sets 'QJ' to avoid precision errors
#define qh_NOmerge
see:
qh_NOmem in mem.c
see user.c/user_eg.c for removing io.o
*/
/*----------------------------------
qh_NOtrace
no tracing if defined
notes:
This saves about 5% space.
#define qh_NOtrace
*/
/*----------------------------------
qh_QHpointer
access global data with pointer or static structure
qh_QHpointer = 1 access globals via a pointer to allocated memory
enables qh_saveqhull() and qh_restoreqhull()
[2010, gcc] costs about 4% in time and 4% in space
[2003, msvc] costs about 8% in time and 2% in space
= 0 qh_qh and qh_qhstat are static data structures
only one instance of qhull() can be active at a time
default value
qh_QHpointer_dllimport and qh_dllimport define qh_qh as __declspec(dllimport) [libqhull.h]
It is required for msvc-2005. It is not needed for gcc.
notes:
all global variables for qhull are in qh, qhmem, and qhstat
qh is defined in libqhull.h
qhmem is defined in mem.h
qhstat is defined in stat.h
C++ build defines qh_QHpointer [libqhullp.pro, libqhullcpp.pro]
see:
user_eg.c for an example
*/
#ifdef qh_QHpointer
#if qh_dllimport
#error QH6207 Qhull error: Use qh_QHpointer_dllimport instead of qh_dllimport with qh_QHpointer
#endif
#else
#define qh_QHpointer 0
#if qh_QHpointer_dllimport
#error QH6234 Qhull error: Use qh_dllimport instead of qh_QHpointer_dllimport when qh_QHpointer is not defined
#endif
#endif
#if 0 /* sample code */
qhT *oldqhA, *oldqhB;
exitcode= qh_new_qhull(dim, numpoints, points, ismalloc,
flags, outfile, errfile);
/* use results from first call to qh_new_qhull */
oldqhA= qh_save_qhull();
exitcode= qh_new_qhull(dimB, numpointsB, pointsB, ismalloc,
flags, outfile, errfile);
/* use results from second call to qh_new_qhull */
oldqhB= qh_save_qhull();
qh_restore_qhull(&oldqhA);
/* use results from first call to qh_new_qhull */
qh_freeqhull(qh_ALL); /* frees all memory used by first call */
qh_restore_qhull(&oldqhB);
/* use results from second call to qh_new_qhull */
qh_freeqhull(!qh_ALL); /* frees long memory used by second call */
qh_memfreeshort(&curlong, &totlong); /* frees short memory and memory allocator */
#endif
/*----------------------------------
qh_QUICKhelp
=1 to use abbreviated help messages, e.g., for degenerate inputs
*/
#define qh_QUICKhelp 0
/*============================================================*/
/*============= -merge constants- ============================*/
/*============================================================*/
/*
These constants effect facet merging. You probably will not need
to modify them. They effect the performance of facet merging.
*/
/*----------------------------------
qh_DIMmergeVertex
max dimension for vertex merging (it is not effective in high-d)
*/
#define qh_DIMmergeVertex 6
/*----------------------------------
qh_DIMreduceBuild
max dimension for vertex reduction during build (slow in high-d)
*/
#define qh_DIMreduceBuild 5
/*----------------------------------
qh_BESTcentrum
if > 2*dim+n vertices, qh_findbestneighbor() tests centrums (faster)
else, qh_findbestneighbor() tests all vertices (much better merges)
qh_BESTcentrum2
if qh_BESTcentrum2 * DIM3 + BESTcentrum < #vertices tests centrums
*/
#define qh_BESTcentrum 20
#define qh_BESTcentrum2 2
/*----------------------------------
qh_BESTnonconvex
if > dim+n neighbors, qh_findbestneighbor() tests nonconvex ridges.
notes:
It is needed because qh_findbestneighbor is slow for large facets
*/
#define qh_BESTnonconvex 15
/*----------------------------------
qh_MAXnewmerges
if >n newmerges, qh_merge_nonconvex() calls qh_reducevertices_centrums.
notes:
It is needed because postmerge can merge many facets at once
*/
#define qh_MAXnewmerges 2
/*----------------------------------
qh_MAXnewcentrum
if <= dim+n vertices (n approximates the number of merges),
reset the centrum in qh_updatetested() and qh_mergecycle_facets()
notes:
needed to reduce cost and because centrums may move too much if
many vertices in high-d
*/
#define qh_MAXnewcentrum 5
/*----------------------------------
qh_COPLANARratio
for 3-d+ merging, qh.MINvisible is n*premerge_centrum
notes:
for non-merging, it's DISTround
*/
#define qh_COPLANARratio 3
/*----------------------------------
qh_DISToutside
When is a point clearly outside of a facet?
Stops search in qh_findbestnew or qh_partitionall
qh_findbest uses qh.MINoutside since since it is only called if no merges.
notes:
'Qf' always searches for best facet
if !qh.MERGING, same as qh.MINoutside.
if qh_USEfindbestnew, increase value since neighboring facets may be ill-behaved
[Note: Zdelvertextot occurs normally with interior points]
RBOX 1000 s Z1 G1e-13 t1001188774 | QHULL Tv
When there is a sharp edge, need to move points to a
clearly good facet; otherwise may be lost in another partitioning.
if too big then O(n^2) behavior for partitioning in cone
if very small then important points not processed
Needed in qh_partitionall for
RBOX 1000 s Z1 G1e-13 t1001032651 | QHULL Tv
Needed in qh_findbestnew for many instances of
RBOX 1000 s Z1 G1e-13 t | QHULL Tv
See:
qh_DISToutside -- when is a point clearly outside of a facet
qh_SEARCHdist -- when is facet coplanar with the best facet?
qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
*/
#define qh_DISToutside ((qh_USEfindbestnew ? 2 : 1) * \
fmax_((qh MERGING ? 2 : 1)*qh MINoutside, qh max_outside))
/*----------------------------------
qh_RATIOnearinside
ratio of qh.NEARinside to qh.ONEmerge for retaining inside points for
qh_check_maxout().
notes:
This is overkill since do not know the correct value.
It effects whether 'Qc' reports all coplanar points
Not used for 'd' since non-extreme points are coplanar
*/
#define qh_RATIOnearinside 5
/*----------------------------------
qh_SEARCHdist
When is a facet coplanar with the best facet?
qh_findbesthorizon: all coplanar facets of the best facet need to be searched.
See:
qh_DISToutside -- when is a point clearly outside of a facet
qh_SEARCHdist -- when is facet coplanar with the best facet?
qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
*/
#define qh_SEARCHdist ((qh_USEfindbestnew ? 2 : 1) * \
(qh max_outside + 2 * qh DISTround + fmax_( qh MINvisible, qh MAXcoplanar)));
/*----------------------------------
qh_USEfindbestnew
Always use qh_findbestnew for qh_partitionpoint, otherwise use
qh_findbestnew if merged new facet or sharpnewfacets.
See:
qh_DISToutside -- when is a point clearly outside of a facet
qh_SEARCHdist -- when is facet coplanar with the best facet?
qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
*/
#define qh_USEfindbestnew (zzval_(Ztotmerge) > 50)
/*----------------------------------
qh_WIDEcoplanar
n*MAXcoplanar or n*MINvisible for a WIDEfacet
if vertex is further than qh.WIDEfacet from the hyperplane
then its ridges are not counted in computing the area, and
the facet's centrum is frozen.
notes:
qh.WIDEfacet= max(qh.MAXoutside,qh_WIDEcoplanar*qh.MAXcoplanar,
qh_WIDEcoplanar * qh.MINvisible);
*/
#define qh_WIDEcoplanar 6
/*----------------------------------
qh_MAXnarrow
max. cosine in initial hull that sets qh.NARROWhull
notes:
If qh.NARROWhull, the initial partition does not make
coplanar points. If narrow, a coplanar point can be
coplanar to two facets of opposite orientations and
distant from the exact convex hull.
Conservative estimate. Don't actually see problems until it is -1.0
*/
#define qh_MAXnarrow -0.99999999
/*----------------------------------
qh_WARNnarrow
max. cosine in initial hull to warn about qh.NARROWhull
notes:
this is a conservative estimate.
Don't actually see problems until it is -1.0. See qh-impre.htm
*/
#define qh_WARNnarrow -0.999999999999999
/*----------------------------------
qh_ZEROdelaunay
a zero Delaunay facet occurs for input sites coplanar with their convex hull
the last normal coefficient of a zero Delaunay facet is within
qh_ZEROdelaunay * qh.ANGLEround of 0
notes:
qh_ZEROdelaunay does not allow for joggled input ('QJ').
You can avoid zero Delaunay facets by surrounding the input with a box.
Use option 'PDk:-n' to explicitly define zero Delaunay facets
k= dimension of input sites (e.g., 3 for 3-d Delaunay triangulation)
n= the cutoff for zero Delaunay facets (e.g., 'PD3:-1e-12')
*/
#define qh_ZEROdelaunay 2
#endif /* qh_DEFuser */
diff --git a/src/libqhull/usermem.c b/src/libqhull/usermem.c
index 2608c18..5794c91 100644
--- a/src/libqhull/usermem.c
+++ b/src/libqhull/usermem.c
@@ -1,64 +1,64 @@
/* ---------------------------------
usermem.c
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.h for data structures, macros, and user-callable functions.
See user.c for qhull-related, redefinable functions
see user.h for user-definable constants
- See userprintf.c for qh_fprintf and userprintf_rbox,c for qh_fprintf_rbox
+ See userprintf.c for qh_fprintf and userprintf_rbox.c for qh_fprintf_rbox
Please report any errors that you fix to qhull@qhull.org
*/
#include "libqhull.h"
#include
/*---------------------------------
qh_exit( exitcode )
exit program
notes:
same as exit()
*/
void qh_exit(int exitcode) {
exit(exitcode);
} /* exit */
/*---------------------------------
qh_free( mem )
free memory
notes:
same as free()
*/
void qh_free(void *mem) {
free(mem);
} /* free */
/*---------------------------------
qh_malloc( mem )
allocate memory
notes:
same as malloc()
*/
void *qh_malloc(size_t size) {
return malloc(size);
} /* malloc */
diff --git a/src/libqhullcpp/Coordinates.cpp b/src/libqhullcpp/Coordinates.cpp
index fa38795..522b45c 100644
--- a/src/libqhullcpp/Coordinates.cpp
+++ b/src/libqhullcpp/Coordinates.cpp
@@ -1,184 +1,184 @@
/****************************************************************************
**
** Copyright (c) 2009-2014 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/Coordinates.cpp#5 $$Change: 1663 $
-** $DateTime: 2014/01/19 17:59:16 $$Author: bbarber $
+** $Id: //main/2011/qhull/src/libqhullcpp/Coordinates.cpp#7 $$Change: 1712 $
+** $DateTime: 2014/03/30 22:34:33 $$Author: bbarber $
**
****************************************************************************/
#include "functionObjects.h"
#include "QhullError.h"
#include "Coordinates.h"
#include
#include
#include
#ifdef _MSC_VER // Microsoft Visual C++ -- warning level 4
#endif
namespace orgQhull {
#//! Coordinates -- vector of coordT (normally double)
#//Element access
// Inefficient without result-value-optimization or implicitly shared object
Coordinates Coordinates::
-mid(int idx, int length) const
+mid(countT idx, countT length) const
{
- int newLength= length;
+ countT newLength= length;
if(length<0 || idx+length > count()){
newLength= count()-idx;
}
Coordinates result;
if(newLength>0){
std::copy(begin()+idx, begin()+(idx+newLength), std::back_inserter(result));
}
return result;
}//mid
coordT Coordinates::
-value(int idx, const coordT &defaultValue) const
+value(countT idx, const coordT &defaultValue) const
{
return ((idx < 0 || idx >= count()) ? defaultValue : (*this)[idx]);
}//value
-#//Operator
+#//!\name GetSet
Coordinates Coordinates::
operator+(const Coordinates &other) const
{
Coordinates result(*this);
std::copy(other.begin(), other.end(), std::back_inserter(result));
return result;
}//operator+
Coordinates & Coordinates::
operator+=(const Coordinates &other)
{
if(&other==this){
Coordinates clone(other);
std::copy(clone.begin(), clone.end(), std::back_inserter(*this));
}else{
std::copy(other.begin(), other.end(), std::back_inserter(*this));
}
return *this;
}//operator+=
#//Read-write
coordT Coordinates::
-takeAt(int idx)
+takeAt(countT idx)
{
coordT c= at(idx);
erase(begin()+idx);
return c;
}//takeAt
coordT Coordinates::
takeLast()
{
coordT c= last();
removeLast();
return c;
}//takeLast
void Coordinates::
-swap(int idx, int other)
+swap(countT idx, countT other)
{
coordT c= at(idx);
at(idx)= at(other);
at(other)= c;
}//swap
#//Search
bool Coordinates::
contains(const coordT &t) const
{
CoordinatesIterator i(*this);
return i.findNext(t);
}//contains
-int Coordinates::
+countT Coordinates::
count(const coordT &t) const
{
CoordinatesIterator i(*this);
- int result= 0;
+ countT result= 0;
while(i.findNext(t)){
++result;
}
return result;
}//count
-int Coordinates::
-indexOf(const coordT &t, int from) const
+countT Coordinates::
+indexOf(const coordT &t, countT from) const
{
if(from<0){
from += count();
if(from<0){
from= 0;
}
}
if(from(i-begin())); // WARN64 coordinate index
+ return (static_cast(i-begin())); // WARN64 coordinate index
}
++i;
}
}
return -1;
}//indexOf
-int Coordinates::
-lastIndexOf(const coordT &t, int from) const
+countT Coordinates::
+lastIndexOf(const coordT &t, countT from) const
{
if(from<0){
from += count();
}else if(from>=count()){
from= count()-1;
}
if(from>=0){
const_iterator i= begin()+from+1;
while(i-- != constBegin()){
if(*i==t){
- return (static_cast(i-begin())); // WARN64 coordinate index
+ return (static_cast(i-begin())); // WARN64 coordinate index
}
}
}
return -1;
}//lastIndexOf
void Coordinates::
removeAll(const coordT &t)
{
MutableCoordinatesIterator i(*this);
while(i.findNext(t)){
i.remove();
}
}//removeAll
}//namespace orgQhull
-#//Global functions
+#//!\name Global functions
using std::endl;
using std::istream;
using std::ostream;
using std::string;
using std::ws;
using orgQhull::Coordinates;
ostream &
operator<<(ostream &os, const Coordinates &cs)
{
Coordinates::const_iterator c= cs.begin();
- for(int i=cs.count(); i--; ){
+ for(countT i=cs.count(); i--; ){
os << *c++ << " ";
}
return os;
}//operator<<
diff --git a/src/libqhullcpp/Coordinates.h b/src/libqhullcpp/Coordinates.h
index 042936b..b30183c 100644
--- a/src/libqhullcpp/Coordinates.h
+++ b/src/libqhullcpp/Coordinates.h
@@ -1,311 +1,305 @@
/****************************************************************************
**
-** Copyright (c) 2009-2012 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/Coordinates.h#6 $$Change: 1464 $
-** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+** Copyright (c) 2009-2014 C.B. Barber. All rights reserved.
+** $Id: //main/2011/qhull/src/libqhullcpp/Coordinates.h#10 $$Change: 1712 $
+** $DateTime: 2014/03/30 22:34:33 $$Author: bbarber $
**
****************************************************************************/
#ifndef QHCOORDINATES_H
#define QHCOORDINATES_H
#include "QhullError.h"
#include "QhullIterator.h"
extern "C" {
- #include "libqhull/qhull_r.h"
+ #include "libqhullr/qhull_ra.h"
}
#include // ptrdiff_t, size_t
#include
+// Requires STL vector class. Can use with another vector class such as QList.
#include
namespace orgQhull {
-#//Types
- //! an allocated vector of point coordinates
- //! Used by PointCoordinates for RboxPoints
- //! A QhullPoint refers to previously allocated coordinates
- class Coordinates;
- class MutableCoordinatesIterator;
-
+#//!\name Defined here
+ //! An std::vector of point coordinates independent of dimension
+ //! Used by PointCoordinates for RboxPoints
+ //! A QhullPoint refers to previously allocated coordinates
+ class Coordinates;
+ class MutableCoordinatesIterator;
class Coordinates {
private:
-#//Fields
+#//!\name Fields
std::vector coordinate_array;
public:
-#//Subtypes
+#//!\name Subtypes
- class const_iterator;
- class iterator;
+ class const_iterator;
+ class iterator;
typedef iterator Iterator;
typedef const_iterator ConstIterator;
typedef coordT value_type;
typedef const value_type *const_pointer;
- typedef const value_type &const_reference;
- typedef value_type *pointer;
- typedef value_type &reference;
+ typedef const value_type & const_reference;
+ typedef value_type * pointer;
+ typedef value_type & reference;
typedef ptrdiff_t difference_type;
- typedef int size_type;
+ typedef countT size_type;
-#//Construct
+#//!\name Construct
Coordinates() {};
explicit Coordinates(const std::vector &other) : coordinate_array(other) {}
Coordinates(const Coordinates &other) : coordinate_array(other.coordinate_array) {}
- Coordinates &operator=(const Coordinates &other) { coordinate_array= other.coordinate_array; return *this; }
- Coordinates &operator=(const std::vector &other) { coordinate_array= other; return *this; }
- ~Coordinates() {}
-
-#//Conversion
+ Coordinates & operator=(const Coordinates &other) { coordinate_array= other.coordinate_array; return *this; }
+ Coordinates & operator=(const std::vector &other) { coordinate_array= other; return *this; }
+ ~Coordinates() {}
- coordT *data() { return isEmpty() ? 0 : &at(0); }
- const coordT *data() const { return const_cast(isEmpty() ? 0 : &at(0)); }
+#//!\name Conversion
#ifndef QHULL_NO_STL
std::vector toStdVector() const { return coordinate_array; }
#endif //QHULL_NO_STL
#ifdef QHULL_USES_QT
- QList toQList() const;
+ QList toQList() const;
#endif //QHULL_USES_QT
-#//GetSet
- int count() const { return static_cast(size()); }
- bool empty() const { return coordinate_array.empty(); }
- bool isEmpty() const { return empty(); }
- bool operator==(const Coordinates &other) const { return coordinate_array==other.coordinate_array; }
- bool operator!=(const Coordinates &other) const { return coordinate_array!=other.coordinate_array; }
- size_t size() const { return coordinate_array.size(); }
-
-#//Element access
- coordT &at(int idx) { return coordinate_array.at(idx); }
- const coordT &at(int idx) const { return coordinate_array.at(idx); }
- coordT &back() { return coordinate_array.back(); }
- const coordT &back() const { return coordinate_array.back(); }
- coordT &first() { return front(); }
- const coordT &first() const { return front(); }
- coordT &front() { return coordinate_array.front(); }
- const coordT &front() const { return coordinate_array.front(); }
- coordT &last() { return back(); }
- const coordT &last() const { return back(); }
- Coordinates mid(int idx, int length= -1) const;
- coordT &operator[](int idx) { return coordinate_array.operator[](idx); }
- const coordT &operator[](int idx) const { return coordinate_array.operator[](idx); }
- coordT value(int idx, const coordT &defaultValue) const;
-
-#//Iterator
+#//!\name GetSet
+ countT count() const { return static_cast(size()); }
+ coordT * data() { return isEmpty() ? 0 : &at(0); }
+ const coordT * data() const { return const_cast(isEmpty() ? 0 : &at(0)); }
+ bool isEmpty() const { return coordinate_array.empty(); }
+ bool operator==(const Coordinates &other) const { return coordinate_array==other.coordinate_array; }
+ bool operator!=(const Coordinates &other) const { return coordinate_array!=other.coordinate_array; }
+ size_t size() const { return coordinate_array.size(); }
+
+#//!\name Element access
+ coordT & at(countT idx) { return coordinate_array.at(idx); }
+ const coordT & at(countT idx) const { return coordinate_array.at(idx); }
+ coordT & back() { return coordinate_array.back(); }
+ const coordT & back() const { return coordinate_array.back(); }
+ coordT & first() { return front(); }
+ const coordT & first() const { return front(); }
+ coordT & front() { return coordinate_array.front(); }
+ const coordT & front() const { return coordinate_array.front(); }
+ coordT & last() { return back(); }
+ const coordT & last() const { return back(); }
+ Coordinates mid(countT idx, countT length= -1) const; //!<\todo countT -1 indicates
+ coordT & operator[](countT idx) { return coordinate_array.operator[](idx); }
+ const coordT & operator[](countT idx) const { return coordinate_array.operator[](idx); }
+ coordT value(countT idx, const coordT &defaultValue) const;
+
+#//!\name Iterator
iterator begin() { return iterator(coordinate_array.begin()); }
const_iterator begin() const { return const_iterator(coordinate_array.begin()); }
const_iterator constBegin() const { return begin(); }
const_iterator constEnd() const { return end(); }
iterator end() { return iterator(coordinate_array.end()); }
const_iterator end() const { return const_iterator(coordinate_array.end()); }
-#//Read-only
+#//!\name GetSet
Coordinates operator+(const Coordinates &other) const;
-#//Modify
+#//!\name Modify
void append(const coordT &c) { push_back(c); }
void clear() { coordinate_array.clear(); }
iterator erase(iterator idx) { return iterator(coordinate_array.erase(idx.base())); }
iterator erase(iterator beginIterator, iterator endIterator) { return iterator(coordinate_array.erase(beginIterator.base(), endIterator.base())); }
- void insert(int before, const coordT &c) { insert(begin()+before, c); }
+ void insert(countT before, const coordT &c) { insert(begin()+before, c); }
iterator insert(iterator before, const coordT &c) { return iterator(coordinate_array.insert(before.base(), c)); }
- void move(int from, int to) { insert(to, takeAt(from)); }
- Coordinates &operator+=(const Coordinates &other);
- Coordinates &operator+=(const coordT &c) { append(c); return *this; }
- Coordinates &operator<<(const Coordinates &other) { return *this += other; }
- Coordinates &operator<<(const coordT &c) { return *this += c; }
+ void move(countT from, countT to) { insert(to, takeAt(from)); }
+ Coordinates & operator+=(const Coordinates &other);
+ Coordinates & operator+=(const coordT &c) { append(c); return *this; }
+ Coordinates & operator<<(const Coordinates &other) { return *this += other; }
+ Coordinates & operator<<(const coordT &c) { return *this += c; }
void pop_back() { coordinate_array.pop_back(); }
void pop_front() { removeFirst(); }
void prepend(const coordT &c) { insert(begin(), c); }
void push_back(const coordT &c) { coordinate_array.push_back(c); }
void push_front(const coordT &c) { insert(begin(), c); }
//removeAll below
- void removeAt(int idx) { erase(begin()+idx); }
+ void removeAt(countT idx) { erase(begin()+idx); }
void removeFirst() { erase(begin()); }
void removeLast() { erase(--end()); }
- void replace(int idx, const coordT &c) { (*this)[idx]= c; }
- void reserve(int i) { coordinate_array.reserve(i); }
- void swap(int idx, int other);
- coordT takeAt(int idx);
+ void replace(countT idx, const coordT &c) { (*this)[idx]= c; }
+ void reserve(countT i) { coordinate_array.reserve(i); }
+ void swap(countT idx, countT other);
+ coordT takeAt(countT idx);
coordT takeFirst() { return takeAt(0); }
coordT takeLast();
-#//Search
+#//!\name Search
bool contains(const coordT &t) const;
- int count(const coordT &t) const;
- int indexOf(const coordT &t, int from = 0) const;
- int lastIndexOf(const coordT &t, int from = -1) const;
+ countT count(const coordT &t) const;
+ countT indexOf(const coordT &t, countT from = 0) const;
+ countT lastIndexOf(const coordT &t, countT from = -1) const;
void removeAll(const coordT &t);
-#//Coordinates::iterator -- from QhullPoints, forwarding to coordinate_array
+#//!\name Coordinates::iterator -- from QhullPoints, forwarding to coordinate_array
// before const_iterator for conversion with comparison operators
class iterator {
private:
std::vector::iterator i;
- friend class const_iterator;
+ friend class const_iterator;
public:
typedef std::random_access_iterator_tag iterator_category;
typedef coordT value_type;
typedef value_type *pointer;
typedef value_type &reference;
typedef ptrdiff_t difference_type;
iterator() {}
iterator(const iterator &other) { i= other.i; }
explicit iterator(const std::vector::iterator &vi) { i= vi; }
- iterator &operator=(const iterator &other) { i= other.i; return *this; }
+ iterator & operator=(const iterator &other) { i= other.i; return *this; }
std::vector::iterator &base() { return i; }
// No operator-> for base types
- coordT &operator*() const { return *i; }
- coordT &operator[](int idx) const { return i[idx]; }
+ coordT & operator*() const { return *i; }
+ coordT & operator[](countT idx) const { return i[idx]; }
bool operator==(const iterator &other) const { return i==other.i; }
bool operator!=(const iterator &other) const { return i!=other.i; }
bool operator<(const iterator &other) const { return i(const iterator &other) const { return i>other.i; }
bool operator>=(const iterator &other) const { return i>=other.i; }
// reinterpret_cast to break circular dependency
bool operator==(const Coordinates::const_iterator &other) const { return *this==reinterpret_cast(other); }
bool operator!=(const Coordinates::const_iterator &other) const { return *this!=reinterpret_cast(other); }
bool operator<(const Coordinates::const_iterator &other) const { return *this(other); }
bool operator<=(const Coordinates::const_iterator &other) const { return *this<=reinterpret_cast(other); }
bool operator>(const Coordinates::const_iterator &other) const { return *this>reinterpret_cast(other); }
bool operator>=(const Coordinates::const_iterator &other) const { return *this>=reinterpret_cast(other); }
iterator operator++() { return iterator(++i); } //FIXUP QH11012 Should return reference, but get reference to temporary
iterator operator++(int) { return iterator(i++); }
iterator operator--() { return iterator(--i); }
iterator operator--(int) { return iterator(i--); }
- iterator operator+=(int idx) { return iterator(i += idx); }
- iterator operator-=(int idx) { return iterator(i -= idx); }
- iterator operator+(int idx) const { return iterator(i+idx); }
- iterator operator-(int idx) const { return iterator(i-idx); }
+ iterator operator+=(countT idx) { return iterator(i += idx); }
+ iterator operator-=(countT idx) { return iterator(i -= idx); }
+ iterator operator+(countT idx) const { return iterator(i+idx); }
+ iterator operator-(countT idx) const { return iterator(i-idx); }
difference_type operator-(iterator other) const { return i-other.i; }
};//Coordinates::iterator
-#//Coordinates::const_iterator
+#//!\name Coordinates::const_iterator
class const_iterator {
private:
std::vector::const_iterator i;
public:
typedef std::random_access_iterator_tag iterator_category;
typedef coordT value_type;
typedef const value_type *pointer;
typedef const value_type &reference;
typedef ptrdiff_t difference_type;
const_iterator() {}
const_iterator(const const_iterator &other) { i= other.i; }
const_iterator(iterator o) : i(o.i) {}
explicit const_iterator(const std::vector::const_iterator &vi) { i= vi; }
const_iterator &operator=(const const_iterator &other) { i= other.i; return *this; }
// No operator-> for base types
// No reference to a base type for () and []
- const coordT &operator*() const { return *i; }
- const coordT &operator[](int idx) const { return i[idx]; }
+ const coordT & operator*() const { return *i; }
+ const coordT & operator[](countT idx) const { return i[idx]; }
bool operator==(const const_iterator &other) const { return i==other.i; }
bool operator!=(const const_iterator &other) const { return i!=other.i; }
bool operator<(const const_iterator &other) const { return i(const const_iterator &other) const { return i>other.i; }
bool operator>=(const const_iterator &other) const { return i>=other.i; }
const_iterator operator++() { return const_iterator(++i); } //FIXUP QH11014 -- too much copying
const_iterator operator++(int) { return const_iterator(i++); }
const_iterator operator--() { return const_iterator(--i); }
const_iterator operator--(int) { return const_iterator(i--); }
- const_iterator operator+=(int idx) { return const_iterator(i += idx); }
- const_iterator operator-=(int idx) { return const_iterator(i -= idx); }
- const_iterator operator+(int idx) const { return const_iterator(i+idx); }
- const_iterator operator-(int idx) const { return const_iterator(i-idx); }
+ const_iterator operator+=(countT idx) { return const_iterator(i += idx); }
+ const_iterator operator-=(countT idx) { return const_iterator(i -= idx); }
+ const_iterator operator+(countT idx) const { return const_iterator(i+idx); }
+ const_iterator operator-(countT idx) const { return const_iterator(i-idx); }
difference_type operator-(const_iterator other) const { return i-other.i; }
};//Coordinates::const_iterator
};//Coordinates
//class CoordinatesIterator
//QHULL_DECLARE_SEQUENTIAL_ITERATOR(Coordinates, coordT)
class CoordinatesIterator
{
typedef Coordinates::const_iterator const_iterator;
- const Coordinates *c;
- const_iterator i;
- public:
- inline CoordinatesIterator(const Coordinates &container)
- : c(&container), i(c->constBegin()) {}
- inline CoordinatesIterator &operator=(const Coordinates &container)
- { c = &container; i = c->constBegin(); return *this; }
- inline void toFront() { i = c->constBegin(); }
- inline void toBack() { i = c->constEnd(); }
- inline bool hasNext() const { return i != c->constEnd(); }
- inline const coordT &next() { return *i++; }
- inline const coordT &peekNext() const { return *i; }
- inline bool hasPrevious() const { return i != c->constBegin(); }
- inline const coordT &previous() { return *--i; }
- inline const coordT &peekPrevious() const { const_iterator p = i; return *--p; }
- inline bool findNext(const coordT &t)
- { while (i != c->constEnd()) if (*i++ == t) return true; return false; }
- inline bool findPrevious(const coordT &t)
- { while (i != c->constBegin()) if (*(--i) == t) return true;
- return false; }
+
+private:
+ const Coordinates * c;
+ const_iterator i;
+
+public:
+ CoordinatesIterator(const Coordinates &container): c(&container), i(c->constBegin()) {}
+ CoordinatesIterator &operator=(const Coordinates &container) { c= &container; i= c->constBegin(); return *this; }
+ ~CoordinatesIterator() {}
+
+ bool findNext(const coordT &t) { while (i != c->constEnd()) if(*i++ == t){ return true;} return false; }
+ bool findPrevious(const coordT &t) { while (i != c->constBegin())if (*(--i) == t){ return true;} return false; }
+ bool hasNext() const { return i != c->constEnd(); }
+ bool hasPrevious() const { return i != c->constBegin(); }
+ const coordT & next() { return *i++; }
+ const coordT & previous() { return *--i; }
+ const coordT & peekNext() const { return *i; }
+ const coordT & peekPrevious() const { const_iterator p= i; return *--p; }
+ void toFront() { i= c->constBegin(); }
+ void toBack() { i= c->constEnd(); }
};//CoordinatesIterator
//class MutableCoordinatesIterator
//QHULL_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(Coordinates, coordT)
class MutableCoordinatesIterator
{
typedef Coordinates::iterator iterator;
typedef Coordinates::const_iterator const_iterator;
- Coordinates *c;
- iterator i, n;
- inline bool item_exists() const { return const_iterator(n) != c->constEnd(); }
- public:
- inline MutableCoordinatesIterator(Coordinates &container)
- : c(&container)
- { i = c->begin(); n = c->end(); }
- inline ~MutableCoordinatesIterator()
- {}
- inline MutableCoordinatesIterator &operator=(Coordinates &container)
- { c = &container;
- i = c->begin(); n = c->end(); return *this; }
- inline void toFront() { i = c->begin(); n = c->end(); }
- inline void toBack() { i = c->end(); n = i; }
- inline bool hasNext() const { return c->constEnd() != const_iterator(i); }
- inline coordT &next() { n = i++; return *n; }
- inline coordT &peekNext() const { return *i; }
- inline bool hasPrevious() const { return c->constBegin() != const_iterator(i); }
- inline coordT &previous() { n = --i; return *n; }
- inline coordT &peekPrevious() const { iterator p = i; return *--p; }
- inline void remove()
- { if (c->constEnd() != const_iterator(n)) { i = c->erase(n); n = c->end(); } }
- inline void setValue(const coordT &t) const { if (c->constEnd() != const_iterator(n)) *n = t; }
- inline coordT &value() { QHULL_ASSERT(item_exists()); return *n; }
- inline const coordT &value() const { QHULL_ASSERT(item_exists()); return *n; }
- inline void insert(const coordT &t) { n = i = c->insert(i, t); ++i; }
- inline bool findNext(const coordT &t)
- { while (c->constEnd() != const_iterator(n = i)) if (*i++ == t) return true; return false; }
- inline bool findPrevious(const coordT &t)
- { while (c->constBegin() != const_iterator(i)) if (*(n = --i) == t) return true;
- n = c->end(); return false; }
+
+private:
+ Coordinates * c;
+ iterator i;
+ iterator n;
+ bool item_exists() const { return const_iterator(n) != c->constEnd(); }
+
+public:
+ MutableCoordinatesIterator(Coordinates &container) : c(&container) { i= c->begin(); n= c->end(); }
+ MutableCoordinatesIterator &operator=(Coordinates &container) { c= &container; i= c->begin(); n= c->end(); return *this; }
+ ~MutableCoordinatesIterator() {}
+
+ bool findNext(const coordT &t) { while(c->constEnd()!=const_iterator(n= i)){ if(*i++==t){ return true;}} return false; }
+ bool findPrevious(const coordT &t) { while(c->constBegin()!=const_iterator(i)){ if(*(n= --i)== t){ return true;}} n= c->end(); return false; }
+ bool hasNext() const { return (c->constEnd()!=const_iterator(i)); }
+ bool hasPrevious() const { return (c->constBegin()!=const_iterator(i)); }
+ void insert(const coordT &t) { n= i= c->insert(i, t); ++i; }
+ coordT & next() { n= i++; return *n; }
+ coordT & peekNext() const { return *i; }
+ coordT & peekPrevious() const { iterator p= i; return *--p; }
+ coordT & previous() { n= --i; return *n; }
+ void remove() { if(c->constEnd()!=const_iterator(n)){ i= c->erase(n); n= c->end();} }
+ void setValue(const coordT &t) const { if(c->constEnd()!=const_iterator(n)){ *n= t;} }
+ void toFront() { i= c->begin(); n= c->end(); }
+ void toBack() { i= c->end(); n= i; }
+ coordT & value() { QHULL_ASSERT(item_exists()); return *n; }
+ const coordT & value() const { QHULL_ASSERT(item_exists()); return *n; }
};//MutableCoordinatesIterator
}//namespace orgQhull
-#//Global functions
+#//!\name Global
std::ostream &operator<<(std::ostream &os, const orgQhull::Coordinates &c);
#endif // QHCOORDINATES_H
diff --git a/src/libqhullcpp/PointCoordinates.cpp b/src/libqhullcpp/PointCoordinates.cpp
index 9aaa09f..be57c60 100644
--- a/src/libqhullcpp/PointCoordinates.cpp
+++ b/src/libqhullcpp/PointCoordinates.cpp
@@ -1,294 +1,342 @@
/****************************************************************************
**
** Copyright (c) 2009-2014 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/PointCoordinates.cpp#6 $$Change: 1464 $
-** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+** $Id: //main/2011/qhull/src/libqhullcpp/PointCoordinates.cpp#11 $$Change: 1797 $
+** $DateTime: 2014/12/15 17:23:41 $$Author: bbarber $
**
****************************************************************************/
#include "QhullError.h"
#include "QhullPoint.h"
#include "PointCoordinates.h"
#include
#include
using std::istream;
using std::string;
using std::ws;
#ifdef _MSC_VER // Microsoft Visual C++ -- warning level 4
#pragma warning( disable : 4996) // function was declared deprecated(strcpy, localtime, etc.)
#endif
namespace orgQhull {
#//! PointCoordinates -- vector of PointCoordinates
-#//Construct
+#//!\name Constructors
+
+//! Qhull and QhullQh constructors are the same
PointCoordinates::
-PointCoordinates()
-: QhullPoints()
+PointCoordinates(const Qhull &q)
+: QhullPoints(q)
, point_coordinates()
-, point_comment()
+, describe_points()
{
makeValid();
}
-#//Construct
PointCoordinates::
-PointCoordinates(int pointDimension)
-: QhullPoints(pointDimension)
+PointCoordinates(const Qhull &q, int pointDimension)
+: QhullPoints(q, pointDimension)
, point_coordinates()
-, point_comment()
+, describe_points()
{
makeValid();
}
PointCoordinates::
-PointCoordinates(const std::string &aComment)
-: QhullPoints()
+PointCoordinates(const Qhull &q, const std::string &aComment)
+: QhullPoints(q)
, point_coordinates()
-, point_comment(aComment)
+, describe_points(aComment)
{
makeValid();
}
PointCoordinates::
-PointCoordinates(int pointDimension, const std::string &aComment)
-: QhullPoints(pointDimension)
+PointCoordinates(const Qhull &q, int pointDimension, const std::string &aComment)
+: QhullPoints(q, pointDimension)
, point_coordinates()
-, point_comment(aComment)
+, describe_points(aComment)
{
makeValid();
}
PointCoordinates::
-PointCoordinates(int pointDimension, const std::string &aComment, int coordinatesCount, const coordT *c)
-: QhullPoints(pointDimension)
+PointCoordinates(const Qhull &q, int pointDimension, const std::string &aComment, countT coordinatesCount, const coordT *c)
+: QhullPoints(q, pointDimension)
, point_coordinates()
-, point_comment(aComment)
+, describe_points(aComment)
+{
+ append(coordinatesCount, c);
+}
+
+PointCoordinates::
+PointCoordinates(QhullQh *qh)
+: QhullPoints(qh)
+, point_coordinates()
+, describe_points()
+{
+ makeValid();
+}
+
+PointCoordinates::
+PointCoordinates(QhullQh *qh, int pointDimension)
+: QhullPoints(qh, pointDimension)
+, point_coordinates()
+, describe_points()
+{
+ makeValid();
+}
+
+PointCoordinates::
+PointCoordinates(QhullQh *qh, const std::string &aComment)
+: QhullPoints(qh)
+, point_coordinates()
+, describe_points(aComment)
+{
+ makeValid();
+}
+
+PointCoordinates::
+PointCoordinates(QhullQh *qh, int pointDimension, const std::string &aComment)
+: QhullPoints(qh, pointDimension)
+, point_coordinates()
+, describe_points(aComment)
+{
+ makeValid();
+}
+
+PointCoordinates::
+PointCoordinates(QhullQh *qh, int pointDimension, const std::string &aComment, countT coordinatesCount, const coordT *c)
+: QhullPoints(qh, pointDimension)
+, point_coordinates()
+, describe_points(aComment)
{
append(coordinatesCount, c);
}
PointCoordinates::
PointCoordinates(const PointCoordinates &other)
: QhullPoints(other)
, point_coordinates(other.point_coordinates)
-, point_comment(other.point_comment)
+, describe_points(other.describe_points)
{
- makeValid();
+ makeValid(); // Update point_first and point_end
}
PointCoordinates & PointCoordinates::
operator=(const PointCoordinates &other)
{
+ QhullPoints::operator=(other);
point_coordinates= other.point_coordinates;
- point_comment= other.point_comment;
- makeValid();
+ describe_points= other.describe_points;
+ makeValid(); // Update point_first and point_end
return *this;
}//operator=
PointCoordinates::
~PointCoordinates()
{ }
-#//GetSet
+#//!\name GetSet
void PointCoordinates::
checkValid() const
{
if(getCoordinates().data()!=data()
|| getCoordinates().count()!=coordinateCount()){
throw QhullError(10060, "Qhull error: first point (%x) is not PointCoordinates.data() or count (%d) is not PointCoordinates.count (%d)", coordinateCount(), getCoordinates().count(), 0.0, data());
}
}//checkValid
void PointCoordinates::
setDimension(int i)
{
if(i<0){
throw QhullError(10062, "Qhull error: can not set PointCoordinates dimension to %d", i);
}
int currentDimension=QhullPoints::dimension();
if(currentDimension!=0 && i!=currentDimension){
throw QhullError(10063, "Qhull error: can not change PointCoordinates dimension (from %d to %d)", currentDimension, i);
}
QhullPoints::setDimension(i);
}//setDimension
-//#Foreach
+#//!\name Foreach
Coordinates::ConstIterator PointCoordinates::
-beginCoordinates(int pointIndex) const
+beginCoordinates(countT pointIndex) const
{
return point_coordinates.begin()+indexOffset(pointIndex);
}
Coordinates::Iterator PointCoordinates::
-beginCoordinates(int pointIndex)
+beginCoordinates(countT pointIndex)
{
return point_coordinates.begin()+indexOffset(pointIndex);
}
-#//Modify
+#//!\name Methods
void PointCoordinates::
-append(int coordinatesCount, const coordT *c)
+append(countT coordinatesCount, const coordT *c)
{
if(coordinatesCount<=0){
return;
}
if(includesCoordinates(c)){
throw QhullError(10065, "Qhull error: can not append a subset of PointCoordinates to itself. The coordinates for point %d may move.", indexOf(c, QhullError::NOthrow));
}
reserveCoordinates(coordinatesCount);
std::copy(c, c+coordinatesCount, std::back_inserter(point_coordinates));
makeValid();
}//append coordT
void PointCoordinates::
append(const PointCoordinates &other)
{
setDimension(other.dimension());
append(other.coordinateCount(), other.data());
}//append PointCoordinates
void PointCoordinates::
append(const QhullPoint &p)
{
setDimension(p.dimension());
append(p.dimension(), p.coordinates());
}//append QhullPoint
void PointCoordinates::
appendComment(const std::string &s){
- if(char c= s[0] && point_comment.empty()){
+ if(char c= s[0] && describe_points.empty()){
if(c=='-' || isdigit(c)){
throw QhullError(10028, "Qhull argument error: comments can not start with a number or minus, %s", 0, 0, 0.0, s.c_str());
}
}
- point_comment += s;
+ describe_points += s;
}//appendComment
//! Read PointCoordinates from istream. First two numbers are dimension and count. A non-digit starts a rboxCommand.
-//! Overwrites point_comment. See qh_readpoints [io.c]
+//! Overwrites describe_points. See qh_readpoints [io.c]
void PointCoordinates::
appendPoints(istream &in)
{
- int inDimension, inCount;
+ int inDimension;
+ countT inCount;
in >> ws >> inDimension >> ws;
if(!in.good()){
in.clear();
string remainder;
getline(in, remainder);
throw QhullError(10005, "Qhull error: input did not start with dimension or count -- %s", 0, 0, 0, remainder.c_str());
}
char c= (char)in.peek();
if(c!='-' && !isdigit(c)){ // Comments start with a non-digit
- getline(in, point_comment);
+ getline(in, describe_points);
in >> ws;
}
in >> inCount >> ws;
if(!in.good()){
in.clear();
string remainder;
getline(in, remainder);
throw QhullError(10009, "Qhull error: input did not start with dimension and count -- %d %s", inDimension, 0, 0, remainder.c_str());
}
c= (char)in.peek();
if(c!='-' && !isdigit(c)){ // Comments start with a non-digit
- getline(in, point_comment);
+ getline(in, describe_points);
in >> ws;
}
if(inCount> p >> ws;
if(in.fail()){
in.clear();
string remainder;
getline(in, remainder);
throw QhullError(10008, "Qhull error: failed to read coordinate %d of point %d\n %s", coordinatesCount % inDimension, coordinatesCount/inDimension, 0, remainder.c_str());
}else{
point_coordinates.push_back(p);
coordinatesCount++;
}
}
if(coordinatesCount != inCount*inDimension){
if(coordinatesCount%inDimension==0){
throw QhullError(10006, "Qhull error: expected %d %d-d PointCoordinates but read %i PointCoordinates", int(inCount), inDimension, 0.0, int(coordinatesCount/inDimension));
}else{
throw QhullError(10012, "Qhull error: expected %d %d-d PointCoordinates but read %i PointCoordinates plus %f extra coordinates", inCount, inDimension, float(coordinatesCount%inDimension), coordinatesCount/inDimension);
}
}
makeValid();
}//appendPoints istream
PointCoordinates PointCoordinates::
operator+(const PointCoordinates &other) const
{
PointCoordinates pc= *this;
pc << other;
return pc;
}//operator+
void PointCoordinates::
-reserveCoordinates(int newCoordinates)
+reserveCoordinates(countT newCoordinates)
{
// vector::reserve is not const
- point_coordinates.reserve((int)point_coordinates.size()+newCoordinates); // WARN64
+ point_coordinates.reserve((countT)point_coordinates.size()+newCoordinates); // WARN64
makeValid();
}//reserveCoordinates
#//Helpers
-int PointCoordinates::
-indexOffset(int i) const {
- int n= i*dimension();
- int coordinatesCount= point_coordinates.count();
+countT PointCoordinates::
+indexOffset(countT i) const {
+ countT n= i*dimension();
+ countT coordinatesCount= point_coordinates.count();
if(i<0 || n>coordinatesCount){
throw QhullError(10061, "Qhull error: point_coordinates is too short (%d) for point %d", coordinatesCount, i);
}
return n;
}
}//namespace orgQhull
-#//Global functions
+#//!\name Global functions
using std::endl;
using std::ostream;
using orgQhull::Coordinates;
using orgQhull::PointCoordinates;
ostream&
operator<<(ostream &os, const PointCoordinates &p)
{
p.checkValid();
- int count= p.count();
+ countT count= p.count();
int dimension= p.dimension();
string comment= p.comment();
if(comment.empty()){
os << dimension << endl;
}else{
os << dimension << " " << comment << endl;
}
os << count << endl;
Coordinates::ConstIterator c= p.beginCoordinates();
- for(int i=0; i
+#include
+
+#ifndef QHULL_NO_STL
#include
+#endif
namespace orgQhull {
-#//Types
- //! Zero or more points with Coordinates, count, and dimension
+#//!\name Defined here
+ //! Zero or more QhullPoints with Coordinates and description
class PointCoordinates;
class PointCoordinates : public QhullPoints {
private:
-#//Field
- Coordinates point_coordinates; //! array of point coordinates
+#//!\name Fields
+ Coordinates point_coordinates; //! std::vector of point coordinates
//! may have extraCoordinates()
- std::string point_comment; //! Comment describing PointCoordinates
+ std::string describe_points; //! Comment describing PointCoordinates
public:
-#//Construct
- PointCoordinates();
- explicit PointCoordinates(int pointDimension);
- explicit PointCoordinates(const std::string &aComment);
- PointCoordinates(int pointDimension, const std::string &aComment);
- PointCoordinates(int pointDimension, const std::string &aComment, int coordinatesCount, const coordT *c); // may be invalid
+#//!\name Construct
+ explicit PointCoordinates(const Qhull &q);
+ PointCoordinates(const Qhull &q, int pointDimension);
+ PointCoordinates(const Qhull &q, const std::string &aComment);
+ PointCoordinates(const Qhull &q, int pointDimension, const std::string &aComment);
+ PointCoordinates(const Qhull &q, int pointDimension, const std::string &aComment, countT coordinatesCount, const coordT *c); // may be invalid
+ //! Use append() and appendPoints() for Coordinates and vector
+ explicit PointCoordinates(QhullQh *qh);
+ PointCoordinates(QhullQh *qh, int pointDimension);
+ PointCoordinates(QhullQh *qh, const std::string &aComment);
+ PointCoordinates(QhullQh *qh, int pointDimension, const std::string &aComment);
+ PointCoordinates(QhullQh *qh, int pointDimension, const std::string &aComment, countT coordinatesCount, const coordT *c); // may be invalid
//! Use append() and appendPoints() for Coordinates and vector
PointCoordinates(const PointCoordinates &other);
- PointCoordinates &operator=(const PointCoordinates &other);
- ~PointCoordinates();
+ PointCoordinates & operator=(const PointCoordinates &other);
+ ~PointCoordinates();
-#//Convert
+#//!\name Convert
//! QhullPoints coordinates, constData, data, count, size
#ifndef QHULL_NO_STL
void append(const std::vector &otherCoordinates) { if(!otherCoordinates.empty()){ append((int)otherCoordinates.size(), &otherCoordinates[0]); } }
std::vector toStdVector() const { return point_coordinates.toStdVector(); }
#endif //QHULL_NO_STL
#ifdef QHULL_USES_QT
void append(const QList &pointCoordinates) { if(!pointCoordinates.isEmpty()){ append(pointCoordinates.count(), &pointCoordinates[0]); } }
QList toQList() const { return point_coordinates.toQList(); }
#endif //QHULL_USES_QT
-#//GetSet
+#//!\name GetSet
//! See QhullPoints for coordinates, coordinateCount, dimension, empty, isEmpty, ==, !=
void checkValid() const;
- std::string comment() const { return point_comment; }
+ std::string comment() const { return describe_points; }
void makeValid() { defineAs(point_coordinates.count(), point_coordinates.data()); }
- const Coordinates &getCoordinates() const { return point_coordinates; }
- void setComment(const std::string &s) { point_comment= s; }
+ const Coordinates & getCoordinates() const { return point_coordinates; }
+ void setComment(const std::string &s) { describe_points= s; }
void setDimension(int i);
private:
- void defineAs(int coordinatesCount, coordT *c) { QhullPoints::defineAs(coordinatesCount, c); }
+ void defineAs(countT coordinatesCount, coordT *c) { QhullPoints::defineAs(coordinatesCount, c); }
//! defineAs() otherwise disabled
public:
-#//ElementAccess
+#//!\name ElementAccess
//! See QhullPoints for at, back, first, front, last, mid, [], value
-#//Foreach
+#//!\name Foreach
//! See QhullPoints for begin, constBegin, end
Coordinates::ConstIterator beginCoordinates() const { return point_coordinates.begin(); }
Coordinates::Iterator beginCoordinates() { return point_coordinates.begin(); }
- Coordinates::ConstIterator beginCoordinates(int pointIndex) const;
- Coordinates::Iterator beginCoordinates(int pointIndex);
+ Coordinates::ConstIterator beginCoordinates(countT pointIndex) const;
+ Coordinates::Iterator beginCoordinates(countT pointIndex);
Coordinates::ConstIterator endCoordinates() const { return point_coordinates.end(); }
Coordinates::Iterator endCoordinates() { return point_coordinates.end(); }
-#//Search
+#//!\name Search
//! See QhullPoints for contains, count, indexOf, lastIndexOf
-#//Read-only
+#//!\name GetSet
PointCoordinates operator+(const PointCoordinates &other) const;
-#//Modify
+#//!\name Modify
//FIXUP QH11001: Add clear() and other modify operators from Coordinates.h. Include QhullPoint::operator=()
- void append(int coordinatesCount, const coordT *c); //! Dimension previously defined
+ void append(countT coordinatesCount, const coordT *c); //! Dimension previously defined
void append(const coordT &c) { append(1, &c); } //! Dimension previously defined
void append(const QhullPoint &p);
//! See convert for std::vector and QList
void append(const Coordinates &c) { append(c.count(), c.data()); }
void append(const PointCoordinates &other);
void appendComment(const std::string &s);
void appendPoints(std::istream &in);
- PointCoordinates &operator+=(const PointCoordinates &other) { append(other); return *this; }
- PointCoordinates &operator+=(const coordT &c) { append(c); return *this; }
- PointCoordinates &operator+=(const QhullPoint &p) { append(p); return *this; }
- PointCoordinates &operator<<(const PointCoordinates &other) { return *this += other; }
- PointCoordinates &operator<<(const coordT &c) { return *this += c; }
- PointCoordinates &operator<<(const QhullPoint &p) { return *this += p; }
+ PointCoordinates & operator+=(const PointCoordinates &other) { append(other); return *this; }
+ PointCoordinates & operator+=(const coordT &c) { append(c); return *this; }
+ PointCoordinates & operator+=(const QhullPoint &p) { append(p); return *this; }
+ PointCoordinates & operator<<(const PointCoordinates &other) { return *this += other; }
+ PointCoordinates & operator<<(const coordT &c) { return *this += c; }
+ PointCoordinates & operator<<(const QhullPoint &p) { return *this += p; }
// reserve() is non-const
- void reserveCoordinates(int newCoordinates);
+ void reserveCoordinates(countT newCoordinates);
-#//Helpers
+#//!\name Helpers
private:
int indexOffset(int i) const;
};//PointCoordinates
// No references to QhullPoint. Prevents use of QHULL_DECLARE_SEQUENTIAL_ITERATOR(PointCoordinates, QhullPoint)
class PointCoordinatesIterator
{
typedef PointCoordinates::const_iterator const_iterator;
+
+private:
const PointCoordinates *c;
- const_iterator i;
- public:
- inline PointCoordinatesIterator(const PointCoordinates &container)
- : c(&container), i(c->constBegin()) {}
- inline PointCoordinatesIterator &operator=(const PointCoordinates &container)
- { c = &container; i = c->constBegin(); return *this; }
- inline void toFront() { i = c->constBegin(); }
- inline void toBack() { i = c->constEnd(); }
- inline bool hasNext() const { return i != c->constEnd(); }
- inline const QhullPoint next() { return *i++; }
- inline const QhullPoint peekNext() const { return *i; }
- inline bool hasPrevious() const { return i != c->constBegin(); }
- inline const QhullPoint previous() { return *--i; }
- inline const QhullPoint peekPrevious() const { const_iterator p = i; return *--p; }
- inline bool findNext(const QhullPoint &t)
- { while (i != c->constEnd()) if (*i++ == t) return true; return false; }
- inline bool findPrevious(const QhullPoint &t)
- { while (i != c->constBegin()) if (*(--i) == t) return true;
- return false; }
+ const_iterator i;
+
+public:
+ PointCoordinatesIterator(const PointCoordinates &container) : c(&container), i(c->constBegin()) {}
+ PointCoordinatesIterator &operator=(const PointCoordinates &container) { c = &container; i = c->constBegin(); return *this; }
+
+ void toFront() { i = c->constBegin(); }
+ void toBack() { i = c->constEnd(); }
+ bool hasNext() const { return i != c->constEnd(); }
+ const QhullPoint next() { return *i++; }
+ const QhullPoint peekNext() const { return *i; }
+ bool hasPrevious() const { return i != c->constBegin(); }
+ const QhullPoint previous() { return *--i; }
+ const QhullPoint peekPrevious() const { const_iterator p = i; return *--p; }
+ bool findNext(const QhullPoint &t) { while(i != c->constEnd()){ if (*i++ == t) return true;} return false; }
+ bool findPrevious(const QhullPoint &t) { while(i != c->constBegin()){ if (*(--i) == t) return true;} return false; }
};//CoordinatesIterator
// FIXUP QH11002: Add MutablePointCoordinatesIterator after adding modify operators
\
}//namespace orgQhull
-#//Global functions
+#//!\name Global
-std::ostream &operator<<(std::ostream &os, const orgQhull::PointCoordinates &p);
+std::ostream & operator<<(std::ostream &os, const orgQhull::PointCoordinates &p);
#endif // QHPOINTCOORDINATES_H
diff --git a/src/libqhullcpp/Qhull.cpp b/src/libqhullcpp/Qhull.cpp
index a34cbcb..aaf2cbd 100644
--- a/src/libqhullcpp/Qhull.cpp
+++ b/src/libqhullcpp/Qhull.cpp
@@ -1,543 +1,313 @@
/****************************************************************************
**
** Copyright (c) 2008-2014 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/Qhull.cpp#7 $$Change: 1645 $
-** $DateTime: 2014/01/15 12:51:30 $$Author: bbarber $
+** $Id: //main/2011/qhull/src/libqhullcpp/Qhull.cpp#15 $$Change: 1799 $
+** $DateTime: 2014/12/17 16:17:40 $$Author: bbarber $
**
****************************************************************************/
#//! Qhull -- invoke qhull from C++
#//! Compile libqhull and Qhull together due to use of setjmp/longjmp()
#include "QhullError.h"
-#include "UsingLibQhull.h"
#include "RboxPoints.h"
#include "QhullQh.h"
#include "QhullFacet.h"
#include "QhullFacetList.h"
#include "Qhull.h"
extern "C" {
- #include "libqhull/qhull_r.h"
+ #include "libqhullr/qhull_ra.h"
}
#include
using std::cerr;
using std::string;
using std::vector;
using std::ostream;
#ifdef _MSC_VER // Microsoft Visual C++ -- warning level 4
#pragma warning( disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
#pragma warning( disable : 4996) // function was declared deprecated(strcpy, localtime, etc.)
#endif
namespace orgQhull {
#//Global variables
-char s_unsupported_options[]=" Fd TI ";
-char s_not_output_options[]= " Fd TI A C d E H P Qb QbB Qbb Qc Qf Qg Qi Qm QJ Qr QR Qs Qt Qv Qx Qz Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q10 Q11 R Tc TC TM TP TR Tv TV TW U v V W ";
+const char s_unsupported_options[]=" Fd TI ";
+const char s_not_output_options[]= " Fd TI A C d E H P Qb QbB Qbb Qc Qf Qg Qi Qm QJ Qr QR Qs Qt Qv Qx Qz Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q10 Q11 R Tc TC TM TP TR Tv TV TW U v V W ";
#//Constructor, destructor, etc.
Qhull::
Qhull()
-: qhull_qh(0)
-, qhull_run_id(UsingLibQhull::NOqhRunId)
+: qh_qh(0)
, origin_point()
-, qhull_status(qh_ERRnone)
-, qhull_dimension(0)
, run_called(false)
-, qh_active(false)
-, qhull_message()
-, error_stream(0)
-, output_stream(0)
, feasiblePoint()
-, useOutputStream(false)
{
- initializeQhull();
+ allocateQhullQh();
}//Qhull
+//! Invokes Qhull on rboxPoints
+//! Same as runQhull()
+//! For rbox commands, see http://www.qhull.org/html/rbox.htm or html/rbox.htm
+//! For qhull commands, see http://www.qhull.org/html/qhull.htm or html/qhull.htm
Qhull::
Qhull(const RboxPoints &rboxPoints, const char *qhullCommand2)
-: qhull_qh(0)
-, qhull_run_id(UsingLibQhull::NOqhRunId)
+: qh_qh(0)
, origin_point()
-, qhull_status(qh_ERRnone)
-, qhull_dimension(0)
, run_called(false)
-, qh_active(false)
-, qhull_message()
-, error_stream(0)
-, output_stream(0)
, feasiblePoint()
-, useOutputStream(false)
{
- initializeQhull();
+ allocateQhullQh();
runQhull(rboxPoints, qhullCommand2);
}//Qhull rbox
+//! Invokes Qhull on a set of input points
+//! Same as runQhull()
+//! For qhull commands, see http://www.qhull.org/html/qhull.htm or html/qhull.htm
Qhull::
-Qhull(const char *rboxCommand2, int pointDimension, int pointCount, const realT *pointCoordinates, const char *qhullCommand2)
-: qhull_qh(0)
-, qhull_run_id(UsingLibQhull::NOqhRunId)
+Qhull(const char *inputComment, int pointDimension, int pointCount, const realT *pointCoordinates, const char *qhullCommand2)
+: qh_qh(0)
, origin_point()
-, qhull_status(qh_ERRnone)
-, qhull_dimension(0)
, run_called(false)
-, qh_active(false)
-, qhull_message()
-, error_stream(0)
-, output_stream(0)
, feasiblePoint()
-, useOutputStream(false)
{
- initializeQhull();
- runQhull(rboxCommand2, pointDimension, pointCount, pointCoordinates, qhullCommand2);
+ allocateQhullQh();
+ runQhull(inputComment, pointDimension, pointCount, pointCoordinates, qhullCommand2);
}//Qhull points
-Qhull::
-Qhull(const Qhull &other)
-: qhull_qh(0)
-, qhull_run_id(UsingLibQhull::NOqhRunId)
-, origin_point()
-, qhull_status(qh_ERRnone)
-, qhull_dimension(0)
-, run_called(false)
-, qh_active(false)
-, qhull_message(other.qhull_message)
-, error_stream(other.error_stream)
-, output_stream(other.output_stream)
-, feasiblePoint(other.feasiblePoint)
-, useOutputStream(other.useOutputStream)
-{
- if(other.initialized()){
- throw QhullError(10069, "Qhull error: can not use Qhull copy constructor if initialized() is true");
- }
- initializeQhull();
-}//copy constructor
-
-Qhull & Qhull::
-operator=(const Qhull &other)
-{
- if(other.initialized() || initialized()){
- throw QhullError(10070, "Qhull error: can not use Qhull copy assignment if initialized() is true");
- }
- qhull_message= other.qhull_message;
- error_stream= other.error_stream;
- output_stream= other.output_stream;
- feasiblePoint= other.feasiblePoint;
- useOutputStream= other.useOutputStream;
- return *this;
-}//copy constructor
-
void Qhull::
-initializeQhull()
+allocateQhullQh()
{
- #if qh_QHpointer
- qhull_qh= new QhullQh;
- qhull_qh->old_qhstat= qh_qhstat;
- qhull_qh->old_tempstack= qhmem.tempstack;
- qh_qh= 0;
- qh_qhstat= 0;
- #else
- qhull_qh= new (&qh_qh) QhullQh;
- qhull_qh->old_qhstat= &qh_qhstat;
- qhull_qh->old_tempstack= qhmem.tempstack;
- #endif
- qhmem.tempstack= 0;
- qhull_run_id= qhull_qh->run_id;
-}//initializeQhull
+ qh_qh= new QhullQh;
+ if(qh_qh!=static_cast(qh_qh)){
+ throw QhullError(10074, "Qhull error: QhullQh at a different address than base type QhT (%d bytes). Please report compiler to qhull.org", (int)(static_cast(qh_qh)-qh_qh));
+ }
+}//allocateQhullQh
Qhull::
~Qhull() throw()
{
- //! UsingLibQhull is required by ~QhullQh
- UsingLibQhull q(this, QhullError::NOthrow);
- if(q.defined()){
- int exitCode = setjmp(qh errexit);
- if(!exitCode){ // no object creation -- destructors skipped on longjmp()
-#if qh_QHpointer
- delete qhull_qh;
- // clears qhull_qh and qh_qh
- qh_qh= 0;
-#else
- qhull_qh->~QhullQh();
- qhull_qh= 0;
-#endif
- qhull_run_id= UsingLibQhull::NOqhRunId;
- // Except for cerr, does not throw errors
- if(hasQhullMessage()){
- cerr<< "\nQhull output at end\n"; //FIXUP QH11005: where should error and log messages go on ~Qhull?
- cerr<hasQhullMessage()){
+ cerr<< "\nQhull output at end\n"; //FIXUP QH11005: where should error and log messages go on ~Qhull?
+ cerr<< qh_qh->qhullMessage();
+ qh_qh->clearQhullMessage();
}
- s_qhull_output= 0; // Set by UsingLibQhull
+ delete qh_qh;
+ qh_qh= 0;
}//~Qhull
-#//Messaging
-
-void Qhull::
-appendQhullMessage(const string &s)
-{
- if(output_stream && useOutputStream && qh USEstdout){ // threading errors caught elsewhere
- *output_stream << s;
- }else if(error_stream){
- *error_stream << s;
- }else{
- qhull_message += s;
- }
-}//appendQhullMessage
-
-//! clearQhullMessage does not throw errors (~Qhull)
-void Qhull::
-clearQhullMessage()
-{
- qhull_status= qh_ERRnone;
- qhull_message.clear();
- RoadError::clearGlobalLog();
-}//clearQhullMessage
-
-//! hasQhullMessage does not throw errors (~Qhull)
-bool Qhull::
-hasQhullMessage() const
-{
- return (!qhull_message.empty() || qhull_status!=qh_ERRnone);
- //FIXUP QH11006 -- inconsistent usage with Rbox. hasRboxMessage just tests rbox_status. No appendRboxMessage()
-}
-
-//! qhullMessage does not throw errors (~Qhull)
-std::string Qhull::
-qhullMessage() const
-{
- if(qhull_message.empty() && qhull_status!=qh_ERRnone){
- return "qhull: no message for error. Check cerr or error stream\n";
- }else{
- return qhull_message;
- }
-}//qhullMessage
-
-int Qhull::
-qhullStatus() const
-{
- return qhull_status;
-}//qhullStatus
-
-void Qhull::
-setErrorStream(ostream *os)
-{
- error_stream= os;
-}//setErrorStream
-
-//! Updates useOutputStream
-void Qhull::
-setOutputStream(ostream *os)
-{
- output_stream= os;
- useOutputStream= (os!=0);
-}//setOutputStream
-
-#//GetSet
+#//!\name GetSet
void Qhull::
checkIfQhullInitialized()
{
if(!initialized()){ // qh_initqhull_buffers() not called
throw QhullError(10023, "Qhull error: checkIfQhullInitialized failed. Call runQhull() first.");
}
}//checkIfQhullInitialized
-//! Setup global state (qh_qh, qh_qhstat, qhmem.tempstack)
-int Qhull::
-runId()
-{
- UsingLibQhull u(this);
- QHULL_UNUSED(u);
-
- return qhull_run_id;
-}//runId
-
-
#//GetValue
double Qhull::
area(){
checkIfQhullInitialized();
- UsingLibQhull q(this);
- if(!qh hasAreaVolume){
- int exitCode = setjmp(qh errexit);
- if(!exitCode){ // no object creation -- destructors skipped on longjmp()
- qh_getarea(qh facet_list);
+ if(!qh_qh->hasAreaVolume){
+ QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
+ qh_getarea(qh_qh, qh_qh->facet_list);
}
- maybeThrowQhullMessage(exitCode);
+ qh_qh->maybeThrowQhullMessage(QH_TRY_status);
}
- return qh totarea;
+ return qh_qh->totarea;
}//area
double Qhull::
volume(){
checkIfQhullInitialized();
- UsingLibQhull q(this);
- if(!qh hasAreaVolume){
- int exitCode = setjmp(qh errexit);
- if(!exitCode){ // no object creation -- destructors skipped on longjmp()
- qh_getarea(qh facet_list);
+ if(!qh_qh->hasAreaVolume){
+ QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
+ qh_getarea(qh_qh, qh_qh->facet_list);
}
- maybeThrowQhullMessage(exitCode);
+ qh_qh->maybeThrowQhullMessage(QH_TRY_status);
}
- return qh totvol;
+ return qh_qh->totvol;
}//volume
-#//ForEach
+#//!\name Foreach
//! Define QhullVertex::neighborFacets().
//! Automatically called if merging facets or computing the Voronoi diagram.
//! Noop if called multiple times.
void Qhull::
defineVertexNeighborFacets(){
checkIfQhullInitialized();
- UsingLibQhull q(this);
- if(!qh hasAreaVolume){
- int exitCode = setjmp(qh errexit);
- if(!exitCode){ // no object creation -- destructors skipped on longjmp()
- qh_vertexneighbors();
+ if(!qh_qh->hasAreaVolume){
+ QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
+ qh_vertexneighbors(qh_qh);
}
- maybeThrowQhullMessage(exitCode);
+ qh_qh->maybeThrowQhullMessage(QH_TRY_status);
}
}//defineVertexNeighborFacets
QhullFacetList Qhull::
facetList() const{
return QhullFacetList(beginFacet(), endFacet());
}//facetList
QhullPoints Qhull::
points() const
{
- return QhullPoints(hullDimension(), qhull_qh->num_points*hullDimension(), qhull_qh->first_point);
+ return QhullPoints(qh_qh, qh_qh->hull_dim, qh_qh->num_points*qh_qh->hull_dim, qh_qh->first_point);
}//points
QhullPointSet Qhull::
otherPoints() const
{
- return QhullPointSet(hullDimension(), qhull_qh->other_points);
+ return QhullPointSet(qh_qh, qh_qh->other_points);
}//otherPoints
//! Return vertices of the convex hull.
QhullVertexList Qhull::
vertexList() const{
return QhullVertexList(beginVertex(), endVertex());
}//vertexList
-#//Modify
+#//!\name Methods
void Qhull::
outputQhull()
{
checkIfQhullInitialized();
- UsingLibQhull q(this);
- int exitCode = setjmp(qh errexit);
- if(!exitCode){ // no object creation -- destructors skipped on longjmp()
- qh_produce_output2();
+ QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
+ qh_produce_output2(qh_qh);
}
- maybeThrowQhullMessage(exitCode);
+ qh_qh->maybeThrowQhullMessage(QH_TRY_status);
}//outputQhull
void Qhull::
outputQhull(const char *outputflags)
{
checkIfQhullInitialized();
- UsingLibQhull q(this);
string cmd(" "); // qh_checkflags skips first word
cmd += outputflags;
char *command= const_cast(cmd.c_str());
- int exitCode = setjmp(qh errexit);
- if(!exitCode){ // no object creation -- destructors skipped on longjmp()
- qh_clear_outputflags();
- char *s = qh qhull_command + strlen(qh qhull_command) + 1; //space
- strncat(qh qhull_command, command, sizeof(qh qhull_command)-strlen(qh qhull_command)-1);
- qh_checkflags(command, s_not_output_options);
- qh_initflags(s);
- qh_initqhull_outputflags();
- if(qh KEEPminArea < REALmax/2
- || (0 != qh KEEParea + qh KEEPmerge + qh GOODvertex
- + qh GOODthreshold + qh GOODpoint + qh SPLITthresholds)){
+ QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
+ qh_clear_outputflags(qh_qh);
+ char *s = qh_qh->qhull_command + strlen(qh_qh->qhull_command) + 1; //space
+ strncat(qh_qh->qhull_command, command, sizeof(qh_qh->qhull_command)-strlen(qh_qh->qhull_command)-1);
+ qh_checkflags(qh_qh, command, const_cast(s_not_output_options));
+ qh_initflags(qh_qh, s);
+ qh_initqhull_outputflags(qh_qh);
+ if(qh_qh->KEEPminArea < REALmax/2
+ || (0 != qh_qh->KEEParea + qh_qh->KEEPmerge + qh_qh->GOODvertex
+ + qh_qh->GOODthreshold + qh_qh->GOODpoint + qh_qh->SPLITthresholds)){
facetT *facet;
- qh ONLYgood= False;
- FORALLfacet_(qh facet_list) {
+ qh_qh->ONLYgood= False;
+ FORALLfacet_(qh_qh->facet_list) {
facet->good= True;
}
- qh_prepare_output();
+ qh_prepare_output(qh_qh);
}
- qh_produce_output2();
- if(qh VERIFYoutput && !qh STOPpoint && !qh STOPcone){
- qh_check_points();
+ qh_produce_output2(qh_qh);
+ if(qh_qh->VERIFYoutput && !qh_qh->STOPpoint && !qh_qh->STOPcone){
+ qh_check_points(qh_qh);
}
}
- maybeThrowQhullMessage(exitCode);
+ qh_qh->maybeThrowQhullMessage(QH_TRY_status);
}//outputQhull
+//! For qhull commands, see http://www.qhull.org/html/qhull.htm or html/qhull.htm
void Qhull::
runQhull(const RboxPoints &rboxPoints, const char *qhullCommand2)
{
runQhull(rboxPoints.comment().c_str(), rboxPoints.dimension(), rboxPoints.count(), &*rboxPoints.coordinates(), qhullCommand2);
}//runQhull, RboxPoints
-//! points is a array of points, input sites ('d' or 'v'), or halfspaces with offset last ('H')
+//! pointCoordinates is a array of points, input sites ('d' or 'v'), or halfspaces with offset last ('H')
//! Derived from qh_new_qhull [user.c]
+//! For rbox commands, see http://www.qhull.org/html/rbox.htm or html/rbox.htm
+//! For qhull commands, see http://www.qhull.org/html/qhull.htm or html/qhull.htm
void Qhull::
-runQhull(const char *rboxCommand2, int pointDimension, int pointCount, const realT *rboxPoints, const char *qhullCommand2)
+runQhull(const char *inputComment, int pointDimension, int pointCount, const realT *pointCoordinates, const char *qhullCommand2)
{
if(run_called){
throw QhullError(10027, "Qhull error: runQhull called twice. Only one call allowed.");
}
run_called= true;
string s("qhull ");
s += qhullCommand2;
char *command= const_cast(s.c_str());
- UsingLibQhull q(this);
- int exitCode = setjmp(qh errexit);
- if(!exitCode){ // no object creation -- destructors skipped on longjmp()
- qh_checkflags(command, s_unsupported_options);
- qh_initflags(command);
- *qh rbox_command= '\0';
- strncat( qh rbox_command, rboxCommand2, sizeof(qh rbox_command)-1);
- if(qh DELAUNAY){
- qh PROJECTdelaunay= True; // qh_init_B() calls qh_projectinput()
+ /* FIXUP
+ int QH_TRY_status;
+ if(qh_qh->NOerrexit){
+ qh_qh->NOerrexit= False;
+ QH_TRY_status= setjmp(qh_qh->errexit);
+ }else{
+ QH_TRY_status= QH_TRY_ERROR;
+ }
+ if(!QH_TRY_status){
+*/
+ QH_TRY_(qh_qh){ // no object creation -- destructors are skipped on longjmp()
+ qh_checkflags(qh_qh, command, const_cast(s_unsupported_options));
+ qh_initflags(qh_qh, command);
+ *qh_qh->rbox_command= '\0';
+ strncat( qh_qh->rbox_command, inputComment, sizeof(qh_qh->rbox_command)-1);
+ if(qh_qh->DELAUNAY){
+ qh_qh->PROJECTdelaunay= True; // qh_init_B() calls qh_projectinput()
}
- pointT *newPoints= const_cast(rboxPoints);
+ pointT *newPoints= const_cast(pointCoordinates);
int newDimension= pointDimension;
int newIsMalloc= False;
- if(qh HALFspace){
+ if(qh_qh->HALFspace){
--newDimension;
initializeFeasiblePoint(newDimension);
- newPoints= qh_sethalfspace_all(pointDimension, pointCount, newPoints, qh feasible_point);
+ newPoints= qh_sethalfspace_all(qh_qh, pointDimension, pointCount, newPoints, qh_qh->feasible_point);
newIsMalloc= True;
}
- qh_init_B(newPoints, pointCount, newDimension, newIsMalloc);
- qhull_dimension= (qh DELAUNAY ? qh hull_dim - 1 : qh hull_dim);
- qh_qhull();
- qh_check_output();
- qh_prepare_output();
- if(qh VERIFYoutput && !qh STOPpoint && !qh STOPcone){
- qh_check_points();
+ qh_init_B(qh_qh, newPoints, pointCount, newDimension, newIsMalloc);
+ qh_qhull(qh_qh);
+ qh_check_output(qh_qh);
+ qh_prepare_output(qh_qh);
+ if(qh_qh->VERIFYoutput && !qh_qh->STOPpoint && !qh_qh->STOPcone){
+ qh_check_points(qh_qh);
}
}
- for(int k= qhull_dimension; k--; ){ // Do not move up (may throw)
+ for(int k= qh_qh->hull_dim; k--; ){ // Do not move into QH_TRY block. It may throw an error
origin_point << 0.0;
}
- maybeThrowQhullMessage(exitCode);
+ qh_qh->maybeThrowQhullMessage(QH_TRY_status);
}//runQhull
#//Helpers -- be careful of allocating C++ objects due to setjmp/longjmp() error handling by qh_... routines
void Qhull::
initializeFeasiblePoint(int hulldim)
{
- if(qh feasible_string){
- qh_setfeasible(hulldim);
+ if(qh_qh->feasible_string){
+ qh_setfeasible(qh_qh, hulldim);
}else{
- if(feasiblePoint.empty()){
- qh_fprintf(qh ferr, 6209, "qhull error: missing feasible point for halfspace intersection. Use option 'Hn,n' or set qh.feasiblePoint\n");
- qh_errexit(qh_ERRmem, NULL, NULL);
+ if(feasiblePoint.isEmpty()){
+ qh_fprintf(qh_qh, qh_qh->ferr, 6209, "qhull error: missing feasible point for halfspace intersection. Use option 'Hn,n' or set qh_qh.feasiblePoint\n");
+ qh_errexit(qh_qh, qh_ERRmem, NULL, NULL);
}
if(feasiblePoint.size()!=(size_t)hulldim){
- qh_fprintf(qh ferr, 6210, "qhull error: dimension of feasiblePoint should be %d. It is %u", hulldim, feasiblePoint.size());
- qh_errexit(qh_ERRmem, NULL, NULL);
+ qh_fprintf(qh_qh, qh_qh->ferr, 6210, "qhull error: dimension of feasiblePoint should be %d. It is %u", hulldim, feasiblePoint.size());
+ qh_errexit(qh_qh, qh_ERRmem, NULL, NULL);
}
- if (!(qh feasible_point= (coordT*)qh_malloc(hulldim * sizeof(coordT)))) {
- qh_fprintf(qh ferr, 6202, "qhull error: insufficient memory for feasible point\n");
- qh_errexit(qh_ERRmem, NULL, NULL);
+ if (!(qh_qh->feasible_point= (coordT*)qh_malloc(hulldim * sizeof(coordT)))) {
+ qh_fprintf(qh_qh, qh_qh->ferr, 6202, "qhull error: insufficient memory for feasible point\n");
+ qh_errexit(qh_qh, qh_ERRmem, NULL, NULL);
}
- coordT *t= qh feasible_point;
+ coordT *t= qh_qh->feasible_point;
// No qh_... routines after here -- longjmp() ignores destructor
for(Coordinates::ConstIterator p=feasiblePoint.begin(); p--------------------------------
-
- qh_fprintf(fp, msgcode, format, list of args )
- fp is ignored (replaces qh_fprintf() in userprintf.c)
- s_qhull_output == Qhull
-
-notes:
- only called from libqhull
- same as fprintf() and RboxPoints::qh_fprintf_rbox()
- fgets() is not trapped like fprintf()
- Do not throw errors from here. Use qh_errexit;
-*/
-extern "C"
-void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... ) {
- va_list args;
-
- using namespace orgQhull;
-
- if(!s_qhull_output){
- fprintf(stderr, "QH10025 Qhull error: UsingLibQhull not declared prior to calling qh_...(). s_qhull_output==NULL.\n");
- qh_exit(10025);
- }
- Qhull *out= s_qhull_output;
- va_start(args, fmt);
- if(msgcode=MSG_ERROR && msgcodeqhull_statusqhull_status>=MSG_WARNING){
- out->qhull_status= msgcode;
- }
- }
- char newMessage[MSG_MAXLEN];
- // RoadError will add the message tag
- vsnprintf(newMessage, sizeof(newMessage), fmt, args);
- out->appendQhullMessage(newMessage);
- va_end(args);
- return;
- }
- if(out->output_stream && out->useOutputStream){
- char newMessage[MSG_MAXLEN];
- vsnprintf(newMessage, sizeof(newMessage), fmt, args);
- *out->output_stream << newMessage;
- va_end(args);
- return;
- }
- // FIXUP QH11008: how do users trap messages and handle input? A callback?
- char newMessage[MSG_MAXLEN];
- vsnprintf(newMessage, sizeof(newMessage), fmt, args);
- out->appendQhullMessage(newMessage);
- va_end(args);
-} /* qh_fprintf */
-
diff --git a/src/libqhullcpp/Qhull.h b/src/libqhullcpp/Qhull.h
index c9eed9f..07f7559 100644
--- a/src/libqhullcpp/Qhull.h
+++ b/src/libqhullcpp/Qhull.h
@@ -1,147 +1,122 @@
/****************************************************************************
**
-** Copyright (c) 2008-2012 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/Qhull.h#4 $$Change: 1464 $
-** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+** Copyright (c) 2008-2014 C.B. Barber. All rights reserved.
+** $Id: //main/2011/qhull/src/libqhullcpp/Qhull.h#12 $$Change: 1799 $
+** $DateTime: 2014/12/17 16:17:40 $$Author: bbarber $
**
****************************************************************************/
#ifndef QHULLCPP_H
#define QHULLCPP_H
-#include "QhullQh.h"
-#include "RboxPoints.h"
-#include "QhullLinkedList.h"
#include "QhullPoint.h"
-#include "QhullPoints.h"
#include "QhullVertex.h"
#include "QhullFacet.h"
-#include
-#include
-#include
-#include
-#include
-
-#if qh_QHpointer != 1
-#error qh_QHpointer is not set. Please set it in user.h or
-#error compile Qhull with -Dqh_QHpointer. The C++ classes
-#error require dynamic allocation for Qhulls global data
-#error structure qhT (QhullQh).
-#endif
-
namespace orgQhull {
/***
Compile qhullcpp and libqhull with the same compiler. setjmp() and longjmp() must be the same.
-*/
-#//Types
- //! Qhull -- run Qhull from C++
- class Qhull;
+ #define QHULL_NO_STL
+ Do not supply conversions to STL
+ Coordinates.h requires . It could be rewritten for another vector class such as QList
+ #define QHULL_USES_QT
+ Supply conversions to QT
+ qhulltest requires QT. It is defined in RoadTest.h
- //Defined elsewhere
+ #define QHULL_ASSERT
+ Defined by QhullError.h
+ It invokes assert()
+*/
+
+#//!\name Used here
class QhullFacetList;
+ class QhullPoints;
+ class QhullQh;
class RboxPoints;
+#//!\name Defined here
+ class Qhull;
+
+//! Interface to Qhull from C++
class Qhull {
private:
-#//Members and friends
- QhullQh *qhull_qh; //! qh_qh for this instance
- int qhull_run_id; //! qh.run_id at initialization (catch multiple runs if !qh_QHpointer)
- Coordinates origin_point; //! origin for qhull_dimension. Set by runQhull()
- int qhull_status; //! qh_ERRnone if valid
- int qhull_dimension; //! Dimension of result (qh.hull_dim or one less for Delaunay/Voronoi)
+#//!\name Members and friends
+ QhullQh * qh_qh; //! qhT for this instance
+ Coordinates origin_point; //! origin for qh_qh->hull_dim. Set by runQhull()
bool run_called; //! True at start of runQhull. Errors if call again.
- bool qh_active; //! True if global pointer qh_qh equals qhull_qh
- std::string qhull_message;
- std::ostream *error_stream; //! overrides errorMessage, use appendQhullMessage()
- std::ostream *output_stream; //! send output to stream
- friend void ::qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
- friend class UsingLibQhull;
-
-#//Attribute
+#//!\name Attribute
public:
Coordinates feasiblePoint; //! feasible point for half-space intersection
- bool useOutputStream; //! Set if using outputStream
// FIXUP QH11003 feasiblePoint useOutputStream as field or getter?
-#//constructor, assignment, destructor, invariant
- Qhull(); //! Qhull::runQhull() must be called next
+#//!\name Constructors
+ Qhull(); //!< call Qhull::runQhull() next
Qhull(const RboxPoints &rboxPoints, const char *qhullCommand2);
- Qhull(const char *rboxCommand2, int pointDimension, int pointCount, const realT *pointCoordinates, const char *qhullCommand2);
- // Throws error if other.initialized(). Needed for return by value and parameter passing
- Qhull(const Qhull &other);
- // Throws error if initialized() or other.initialized(). Needed for vector
- Qhull &operator=(const Qhull &other);
- ~Qhull() throw();
+ Qhull(const char *inputComment, int pointDimension, int pointCount, const realT *pointCoordinates, const char *qhullCommand2);
+ ~Qhull() throw();
+private: // Disable copy constructor and assignment. Qhull owns QhullQh.
+ Qhull(const Qhull &);
+ Qhull &operator=(const Qhull &);
+
private:
- void initializeQhull();
+ void allocateQhullQh();
public:
-#//virtual methods
- //FIXUP QH11004 -- qh_memfree, etc. as virtual?
-
-#//Messaging
- void appendQhullMessage(const std::string &s);
- void clearQhullMessage();
- std::string qhullMessage() const;
- bool hasQhullMessage() const;
- int qhullStatus() const;
- void setErrorStream(std::ostream *os);
- void setOutputStream(std::ostream *os);
-
-#//GetSet
- void checkIfQhullInitialized();
- bool initialized() const { return qhull_dimension>0; }
- int dimension() const { return qhull_dimension; }
- int hullDimension() const { return qhullQh()->hull_dim; }
- // non-const due to QhullPoint
- QhullPoint origin() { QHULL_ASSERT(initialized()); return QhullPoint(dimension(), origin_point.data()); }
- QhullQh *qhullQh() const { return qhull_qh; };
- int runId(); // Modifies my_qhull
-
-#//GetQh -- access to qhT (Qhull's global data structure)
- const char *qhullCommand() const { return qhull_qh->qhull_command; }
- const char *rboxCommand() const { return qhull_qh->rbox_command; }
- int facetCount() const { return qhull_qh->num_facets; }
- int vertexCount() const { return qhull_qh->num_vertices; }
-
-#//GetValue
- double area();
- double volume();
-#//ForEach
- QhullFacet beginFacet() const { return QhullFacet(qhull_qh->facet_list); }
- QhullVertex beginVertex() const { return QhullVertex(qhull_qh->vertex_list); }
+#//!\name GetSet
+ void checkIfQhullInitialized();
+ int dimension() const { return qh_qh->input_dim; } //!< Dimension of input and result
+ countT facetCount() const { return qh_qh->num_facets; }
+ int hullDimension() const { return qh_qh->hull_dim; } //!< Dimension of the computed hull
+ bool initialized() const { return (qh_qh->hull_dim>0); }
+ const char * inputComment() const { return qh_qh->rbox_command; }
+ //! non-const due to QhullPoint
+ QhullPoint origin() { QHULL_ASSERT(initialized()); return QhullPoint(qh_qh, origin_point.data()); }
+ QhullQh * qh() const { return qh_qh; };
+ const char * qhullCommand() const { return qh_qh->qhull_command; }
+ const char * rboxCommand() const { return qh_qh->rbox_command; }
+ countT vertexCount() const { return qh_qh->num_vertices; }
+
+#//!\name GetEpsilon
+ double angleEpsilon() const { return qh_qh->angleEpsilon(); } //!< Epsilon for hyperplane angle equality
+ double distanceEpsilon() const { return qh_qh->distanceEpsilon(); } //!< Epsilon for distance to hyperplane
+ double factorEpsilon() const { return qh_qh->factorEpsilon(); } //!< Factor for angleEpsilon and distanceEpsilon
+ void setFactorEpsilon(double a) { qh_qh->setFactorEpsilon(a); }
+
+#//!\name ForEach
+ QhullFacet beginFacet() const { return QhullFacet(qh_qh, qh_qh->facet_list); }
+ QhullVertex beginVertex() const { return QhullVertex(qh_qh, qh_qh->vertex_list); }
void defineVertexNeighborFacets(); //!< Automatically called if merging facets or Voronoi diagram
- QhullFacet endFacet() const { return QhullFacet(qhull_qh->facet_tail); }
- QhullVertex endVertex() const { return QhullVertex(qhull_qh->vertex_tail); }
+ QhullFacet endFacet() const { return QhullFacet(qh_qh, qh_qh->facet_tail); }
+ QhullVertex endVertex() const { return QhullVertex(qh_qh, qh_qh->vertex_tail); }
QhullFacetList facetList() const;
QhullFacet firstFacet() const { return beginFacet(); }
QhullVertex firstVertex() const { return beginVertex(); }
QhullPoints points() const;
QhullPointSet otherPoints() const;
//! Same as points().coordinates()
- coordT *pointCoordinateBegin() const { return qhull_qh->first_point; }
- coordT *pointCoordinateEnd() const { return qhull_qh->first_point + qhull_qh->num_points*qhull_qh->hull_dim; }
+ coordT * pointCoordinateBegin() const { return qh_qh->first_point; }
+ coordT * pointCoordinateEnd() const { return qh_qh->first_point + qh_qh->num_points*qh_qh->hull_dim; }
QhullVertexList vertexList() const;
-#//Modify
+#//!\name Methods
+ double area();
+ void checkAndFreeQhullMemory() { qh_qh->checkAndFreeQhullMemory(); }
void outputQhull();
void outputQhull(const char * outputflags);
void runQhull(const RboxPoints &rboxPoints, const char *qhullCommand2);
- void runQhull(const char *rboxCommand2, int pointDimension, int pointCount, const realT *rboxPoints, const char *qhullCommand2);
+ void runQhull(const char *inputComment, int pointDimension, int pointCount, const realT *pointCoordinates, const char *qhullCommand2);
+ double volume();
+#//!\name Helpers
private:
-#//Helpers
void initializeFeasiblePoint(int hulldim);
- void maybeThrowQhullMessage(int exitCode);
- void maybeThrowQhullMessage(int exitCode, int noThrow) throw();
};//Qhull
}//namespace orgQhull
#endif // QHULLCPP_H
diff --git a/src/libqhullcpp/QhullError.h b/src/libqhullcpp/QhullError.h
index 861737b..da39d3a 100644
--- a/src/libqhullcpp/QhullError.h
+++ b/src/libqhullcpp/QhullError.h
@@ -1,64 +1,62 @@
/****************************************************************************
**
-** Copyright (c) 2008-2012 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/QhullError.h#5 $$Change: 1490 $
-** $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $
+** Copyright (c) 2008-2014 C.B. Barber. All rights reserved.
+** $Id: //main/2011/qhull/src/libqhullcpp/QhullError.h#11 $$Change: 1799 $
+** $DateTime: 2014/12/17 16:17:40 $$Author: bbarber $
**
****************************************************************************/
#ifndef QHULLERROR_H
#define QHULLERROR_H
#include "RoadError.h"
+// No dependencies on libqhull
+#ifndef QHULL_ASSERT
+#define QHULL_ASSERT assert
#include
-#include
-#include
+#endif
namespace orgQhull {
-#//Types
+#//!\name Defined here
//! QhullError -- std::exception class for Qhull
class QhullError;
class QhullError : public RoadError {
public:
-#//Constants
+#//!\name Constants
enum {
QHULLfirstError= 10000, //MSG_QHULL_ERROR in Qhull's user.h
- QHULLlastError= 10070,
+ QHULLlastError= 10076,
NOthrow= 1 //! For flag to UsingLibQhull()
};
-#//Constructors
+#//!\name Constructors
// default constructors
QhullError() : RoadError() {};
QhullError(const QhullError &other) : RoadError(other) {}
QhullError(int code, const std::string &message) : RoadError(code, message) {};
QhullError(int code, const char *fmt) : RoadError(code, fmt) {};
QhullError(int code, const char *fmt, int d) : RoadError(code, fmt, d) {};
QhullError(int code, const char *fmt, int d, int d2) : RoadError(code, fmt, d, d2) {};
QhullError(int code, const char *fmt, int d, int d2, float f) : RoadError(code, fmt, d, d2, f) {};
QhullError(int code, const char *fmt, int d, int d2, float f, const char *s) : RoadError(code, fmt, d, d2, f, s) {};
QhullError(int code, const char *fmt, int d, int d2, float f, const void *x) : RoadError(code, fmt, d, d2, f, x) {};
QhullError(int code, const char *fmt, int d, int d2, float f, int i) : RoadError(code, fmt, d, d2, f, i) {};
QhullError(int code, const char *fmt, int d, int d2, float f, long long i) : RoadError(code, fmt, d, d2, f, i) {};
QhullError(int code, const char *fmt, int d, int d2, float f, double e) : RoadError(code, fmt, d, d2, f, e) {};
QhullError &operator=(const QhullError &other) { this->RoadError::operator=(other); return *this; }
~QhullError() throw() {}
};//class QhullError
-#ifndef QHULL_1
- #define QHULL_ASSERT assert
-
-#endif
}//namespace orgQhull
-#//Global functions
+#//!\name Global
inline std::ostream &operator<<(std::ostream &os, const orgQhull::QhullError &e) { return os << e.what(); }
#endif // QHULLERROR_H
diff --git a/src/libqhullcpp/QhullFacet.cpp b/src/libqhullcpp/QhullFacet.cpp
index ca25d0e..ac5780d 100644
--- a/src/libqhullcpp/QhullFacet.cpp
+++ b/src/libqhullcpp/QhullFacet.cpp
@@ -1,524 +1,506 @@
/****************************************************************************
**
** Copyright (c) 2008-2014 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/QhullFacet.cpp#7 $$Change: 1464 $
-** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+** $Id: //main/2011/qhull/src/libqhullcpp/QhullFacet.cpp#13 $$Change: 1797 $
+** $DateTime: 2014/12/15 17:23:41 $$Author: bbarber $
**
****************************************************************************/
#//! QhullFacet -- Qhull's facet structure, facetT, as a C++ class
#include "QhullError.h"
+#include "Qhull.h"
#include "QhullSet.h"
#include "QhullPoint.h"
#include "QhullPointSet.h"
#include "QhullRidge.h"
#include "QhullFacet.h"
#include "QhullFacetSet.h"
#include "QhullVertex.h"
#include
using std::endl;
-using std::string;
-using std::vector;
using std::ostream;
#ifdef _MSC_VER // Microsoft Visual C++ -- warning level 4
#pragma warning( disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
#pragma warning( disable : 4996) // function was declared deprecated(strcpy, localtime, etc.)
#endif
namespace orgQhull {
-#//class statics
+#//!\name Class objects
facetT QhullFacet::
- s_empty_facet= {0,0,0,0,{0},
- 0,0,0,0,0,
- 0,0,0,0,0,
- 0,0,0,0,0,
- 0,0,0,0,0,
- 0,0,0,0,0,
- 0,0,0,0,0,
- 0,0,0,0};
-
-#//GetSet
-
-int QhullFacet::
-dimension() const
+s_empty_facet= {0,0,0,0,{0},
+ 0,0,0,0,0,
+ 0,0,0,0,0,
+ 0,0,0,0,0,
+ 0,0,0,0,0,
+ 0,0,0,0,0,
+ 0,0,0,0,0,
+ 0,0,0,0};
+
+#//!\name Constructors
+
+QhullFacet::
+QhullFacet(const Qhull &q)
+: qh_facet(&s_empty_facet)
+, qh_qh(q.qh())
{
- if(qh_facet->ridges){
- setT *s= qh_facet->ridges;
- ridgeT *r= reinterpret_cast(SETfirst_(s));
- return r ? QhullSetBase::count(r->vertices)+1 : 0;
- }else{
- return QhullSetBase::count(qh_facet->vertices);
- }
-}//dimension
+}
+
+QhullFacet::
+QhullFacet(const Qhull &q, facetT *f)
+: qh_facet(f ? f : &s_empty_facet)
+, qh_qh(q.qh())
+{
+}
-//! Return voronoi center or facet centrum. Derived from qh_printcenter [io.c]
+#//!\name GetSet
+
+//! Return voronoi center or facet centrum. Derived from qh_printcenter [io_r.c]
//! printFormat=qh_PRINTtriangles if return centrum of a Delaunay facet
//! Sets center if needed
//! Code duplicated for PrintCenter and getCenter
-//! .empty() if none or qh_INFINITE
+//! Returns QhullPoint() if none or qh_INFINITE
QhullPoint QhullFacet::
-getCenter(int qhRunId, qh_PRINT printFormat)
+getCenter(qh_PRINT printFormat)
{
- UsingLibQhull q(qhRunId);
-
- if(qh CENTERtype==qh_ASvoronoi){
- if(!qh_facet->normal || !qh_facet->upperdelaunay || !qh ATinfinity){
+ if(qh_qh->CENTERtype==qh_ASvoronoi){
+ if(!qh_facet->normal || !qh_facet->upperdelaunay || !qh_qh->ATinfinity){
if(!qh_facet->center){
- int exitCode = setjmp(qh errexit);
- if(!exitCode){ // no object creation -- destructors skipped on longjmp()
- qh_facet->center= qh_facetcenter(qh_facet->vertices);
+ QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
+ qh_facet->center= qh_facetcenter(qh_qh, qh_facet->vertices);
}
- q.maybeThrowQhullMessage(exitCode);
+ qh_qh->maybeThrowQhullMessage(QH_TRY_status);
}
- return QhullPoint(qh hull_dim-1, qh_facet->center);
+ return QhullPoint(qh_qh, qh_qh->hull_dim-1, qh_facet->center);
}
- }else if(qh CENTERtype==qh_AScentrum){
- volatile int numCoords= qh hull_dim;
- if(printFormat==qh_PRINTtriangles && qh DELAUNAY){
+ }else if(qh_qh->CENTERtype==qh_AScentrum){
+ volatile int numCoords= qh_qh->hull_dim;
+ if(printFormat==qh_PRINTtriangles && qh_qh->DELAUNAY){
numCoords--;
}
if(!qh_facet->center){
- int exitCode = setjmp(qh errexit);
- if(!exitCode){ // no object creation -- destructors skipped on longjmp()
- qh_facet->center= qh_getcentrum(getFacetT());
+ QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
+ qh_facet->center= qh_getcentrum(qh_qh, getFacetT());
}
- q.maybeThrowQhullMessage(exitCode);
+ qh_qh->maybeThrowQhullMessage(QH_TRY_status);
}
- return QhullPoint(numCoords, qh_facet->center);
+ return QhullPoint(qh_qh, numCoords, qh_facet->center);
}
- return QhullPoint();
+ return QhullPoint(qh_qh);
}//getCenter
//! Return innerplane clearly below the vertices
-//! from io.c[qh_PRINTinner]
+//! from io_r.c[qh_PRINTinner]
QhullHyperplane QhullFacet::
-innerplane(int qhRunId) const{
- UsingLibQhull q(qhRunId);
+innerplane() const{
realT inner;
// Does not error
- qh_outerinner(const_cast(getFacetT()), NULL, &inner);
+ qh_outerinner(qh_qh, const_cast(getFacetT()), NULL, &inner);
QhullHyperplane h= hyperplane();
h.setOffset(h.offset()-inner); //inner is negative
return h;
}//innerplane
//! Return outerplane clearly above all points
-//! from io.c[qh_PRINTouter]
+//! from io_r.c[qh_PRINTouter]
QhullHyperplane QhullFacet::
-outerplane(int qhRunId) const{
- UsingLibQhull q(qhRunId);
+outerplane() const{
realT outer;
// Does not error
- qh_outerinner(const_cast(getFacetT()), &outer, NULL);
+ qh_outerinner(qh_qh, const_cast(getFacetT()), &outer, NULL);
QhullHyperplane h= hyperplane();
h.setOffset(h.offset()-outer); //outer is positive
return h;
}//outerplane
//! Set by qh_triangulate for option 'Qt'.
//! Errors if tricoplanar and facetArea() or qh_getarea() called first.
QhullFacet QhullFacet::
tricoplanarOwner() const
{
if(qh_facet->tricoplanar){
if(qh_facet->isarea){
throw QhullError(10018, "Qhull error: facetArea() or qh_getarea() previously called. triCoplanarOwner() is not available.");
}
- return qh_facet->f.triowner;
+ return QhullFacet(qh_qh, qh_facet->f.triowner);
}
- return 0; // FIXUP QH11009 Should false be the NULL facet or empty facet
+ return QhullFacet(qh_qh);
}//tricoplanarOwner
QhullPoint QhullFacet::
-voronoiVertex(int qhRunId)
+voronoiVertex()
{
- if(
-#if qh_QHpointer
- !qh_qh ||
-#endif
- qh CENTERtype!=qh_ASvoronoi){
+ if(qh_qh->CENTERtype!=qh_ASvoronoi){
throw QhullError(10052, "Error: QhullFacet.voronoiVertex() requires option 'v' (qh_ASvoronoi)");
}
- return getCenter(qhRunId);
+ return getCenter();
}//voronoiVertex
#//Value
//! Disables tricoplanarOwner()
double QhullFacet::
-facetArea(int qhRunId)
+facetArea()
{
if(!qh_facet->isarea){
- UsingLibQhull q(qhRunId);
- int exitCode = setjmp(qh errexit);
- if(!exitCode){ // no object creation -- destructors skipped on longjmp()
- qh_facet->f.area= qh_facetarea(qh_facet);
+ QH_TRY_(qh_qh){ // no object creation -- destructors skipped on longjmp()
+ qh_facet->f.area= qh_facetarea(qh_qh, qh_facet);
qh_facet->isarea= True;
}
- q.maybeThrowQhullMessage(exitCode);
+ qh_qh->maybeThrowQhullMessage(QH_TRY_status);
}
return qh_facet->f.area;
}//facetArea
-#//Foreach
+#//!\name Foreach
QhullPointSet QhullFacet::
coplanarPoints() const
{
- return QhullPointSet(dimension(), qh_facet->coplanarset);
+ return QhullPointSet(qh_qh, qh_facet->coplanarset);
}//coplanarPoints
QhullFacetSet QhullFacet::
neighborFacets() const
{
- return QhullFacetSet(qh_facet->neighbors);
+ return QhullFacetSet(qh_qh, qh_facet->neighbors);
}//neighborFacets
QhullPointSet QhullFacet::
outsidePoints() const
{
- return QhullPointSet(dimension(), qh_facet->outsideset);
+ return QhullPointSet(qh_qh, qh_facet->outsideset);
}//outsidePoints
QhullRidgeSet QhullFacet::
ridges() const
{
- return QhullRidgeSet(qh_facet->ridges);
+ return QhullRidgeSet(qh_qh, qh_facet->ridges);
}//ridges
QhullVertexSet QhullFacet::
vertices() const
{
- return QhullVertexSet(qh_facet->vertices);
+ return QhullVertexSet(qh_qh, qh_facet->vertices);
}//vertices
-
}//namespace orgQhull
-#//operator<<
+#//!\name GetSet<<
using std::ostream;
using orgQhull::QhullFacet;
using orgQhull::QhullFacetSet;
using orgQhull::QhullPoint;
using orgQhull::QhullPointSet;
using orgQhull::QhullRidge;
using orgQhull::QhullRidgeSet;
using orgQhull::QhullSetBase;
using orgQhull::QhullVertexSet;
-using orgQhull::UsingLibQhull;
ostream &
operator<<(ostream &os, const QhullFacet::PrintFacet &pr)
{
QhullFacet f= *pr.facet;
if(f.getFacetT()==0){ // Special values from set iterator
os << " NULLfacet" << endl;
return os;
}
if(f.getFacetT()==qh_MERGEridge){
os << " MERGEridge" << endl;
return os;
}
if(f.getFacetT()==qh_DUPLICATEridge){
os << " DUPLICATEridge" << endl;
return os;
}
- os << f.printHeader(pr.run_id);
+ os << f.printHeader();
if(!f.ridges().isEmpty()){
- os << f.printRidges(pr.run_id);
+ os << f.printRidges();
}
return os;
}//operator<< PrintFacet
-//! Print Voronoi center or facet centrum to stream. Same as qh_printcenter [io.c]
+//! Print Voronoi center or facet centrum to stream. Same as qh_printcenter [_r.]
//! Code duplicated for PrintCenter and getCenter
//! Sets center if needed
ostream &
operator<<(ostream &os, const QhullFacet::PrintCenter &pr)
{
facetT *f= pr.facet->getFacetT();
- if(qh CENTERtype!=qh_ASvoronoi && qh CENTERtype!=qh_AScentrum){
+ if(pr.facet->qh()->CENTERtype!=qh_ASvoronoi && pr.facet->qh()->CENTERtype!=qh_AScentrum){
return os;
}
if (pr.message){
os << pr.message;
}
int numCoords;
- if(qh CENTERtype==qh_ASvoronoi){
- numCoords= qh hull_dim-1;
- if(!f->normal || !f->upperdelaunay || !qh ATinfinity){
+ if(pr.facet->qh()->CENTERtype==qh_ASvoronoi){
+ numCoords= pr.facet->qh()->hull_dim-1;
+ if(!f->normal || !f->upperdelaunay || !pr.facet->qh()->ATinfinity){
if(!f->center){
- f->center= qh_facetcenter(f->vertices);
+ f->center= qh_facetcenter(pr.facet->qh(), f->vertices);
}
for(int k=0; kcenter[k] << " "; // FIXUP QH11010 qh_REAL_1
}
}else{
for(int k=0; kqh()->hull_dim;
+ if(pr.print_format==qh_PRINTtriangles && pr.facet->qh()->DELAUNAY){
numCoords--;
}
if(!f->center){
- f->center= qh_getcentrum(f);
+ f->center= qh_getcentrum(pr.facet->qh(), f);
}
for(int k=0; kcenter[k] << " "; // FIXUP QH11010 qh_REAL_1
}
}
if(pr.print_format==qh_PRINTgeom && numCoords==2){
os << " 0";
}
os << endl;
return os;
}//operator<< PrintCenter
-//! Print flags for facet to stream. Space prefix. From qh_printfacetheader [io.c]
+//! Print flags for facet to stream. Space prefix. From qh_printfacetheader [io_r.c]
ostream &
operator<<(ostream &os, const QhullFacet::PrintFlags &p)
{
const facetT *f= p.facet->getFacetT();
if(p.message){
os << p.message;
}
os << (p.facet->isTopOrient() ? " top" : " bottom");
if(p.facet->isSimplicial()){
os << " simplicial";
}
if(p.facet->isTriCoplanar()){
os << " tricoplanar";
}
if(p.facet->isUpperDelaunay()){
os << " upperDelaunay";
}
if(f->visible){
os << " visible";
}
if(f->newfacet){
os << " new";
}
if(f->tested){
os << " tested";
}
if(!f->good){
os << " notG";
}
if(f->seen){
os << " seen";
}
if(f->coplanar){
os << " coplanar";
}
if(f->mergehorizon){
os << " mergehorizon";
}
if(f->keepcentrum){
os << " keepcentrum";
}
if(f->dupridge){
os << " dupridge";
}
if(f->mergeridge && !f->mergeridge2){
os << " mergeridge1";
}
if(f->mergeridge2){
os << " mergeridge2";
}
if(f->newmerge){
os << " newmerge";
}
if(f->flipped){
os << " flipped";
}
if(f->notfurthest){
os << " notfurthest";
}
if(f->degenerate){
os << " degenerate";
}
if(f->redundant){
os << " redundant";
}
os << endl;
return os;
}//operator<< PrintFlags
-//! Print header for facet to stream. Space prefix. From qh_printfacetheader [io.c]
+//! Print header for facet to stream. Space prefix. From qh_printfacetheader [io_r.c]
ostream &
operator<<(ostream &os, const QhullFacet::PrintHeader &pr)
{
QhullFacet facet= *pr.facet;
facetT *f= facet.getFacetT();
os << "- f" << facet.id() << endl;
os << facet.printFlags(" - flags:");
if(f->isarea){
os << " - area: " << f->f.area << endl; //FIXUP QH11010 2.2g
- }else if(qh NEWfacets && f->visible && f->f.replace){
+ }else if(pr.facet->qh()->NEWfacets && f->visible && f->f.replace){
os << " - replacement: f" << f->f.replace->id << endl;
}else if(f->newfacet){
if(f->f.samecycle && f->f.samecycle != f){
os << " - shares same visible/horizon as f" << f->f.samecycle->id << endl;
}
}else if(f->tricoplanar /* !isarea */){
if(f->f.triowner){
os << " - owner of normal & centrum is facet f" << f->f.triowner->id << endl;
}
}else if(f->f.newcycle){
os << " - was horizon to f" << f->f.newcycle->id << endl;
}
if(f->nummerge){
os << " - merges: " << f->nummerge << endl;
}
os << facet.hyperplane().print(" - normal: ", "\n - offset: "); // FIXUP QH11010 %10.7g
- if(qh CENTERtype==qh_ASvoronoi || f->center){
- os << facet.printCenter(pr.run_id, qh_PRINTfacets, " - center: ");
+ if(pr.facet->qh()->CENTERtype==qh_ASvoronoi || f->center){
+ os << facet.printCenter(qh_PRINTfacets, " - center: ");
}
#if qh_MAXoutside
- if(f->maxoutside > qh DISTround){
+ if(f->maxoutside > pr.facet->qh()->DISTround){
os << " - maxoutside: " << f->maxoutside << endl; //FIXUP QH11010 %10.7g
}
#endif
QhullPointSet ps= facet.outsidePoints();
if(!ps.isEmpty()){
QhullPoint furthest= ps.last();
if (ps.size() < 6) {
- os << " - outside set(furthest p" << furthest.id(pr.run_id) << "):" << endl;
+ os << " - outside set(furthest p" << furthest.id() << "):" << endl;
for(QhullPointSet::iterator i=ps.begin(); i!=ps.end(); ++i){
QhullPoint p= *i;
- os << p.print(pr.run_id, " ");
+ os << p.print(" ");
}
}else if(ps.size()<21){
- os << ps.print(pr.run_id, " - outside set:");
+ os << ps.print(" - outside set:");
}else{
os << " - outside set: " << ps.size() << " points.";
- os << furthest.print(pr.run_id, " Furthest");
+ os << furthest.print(" Furthest");
}
#if !qh_COMPUTEfurthest
os << " - furthest distance= " << f->furthestdist << endl; //FIXUP QH11010 %2.2g
#endif
}
QhullPointSet cs= facet.coplanarPoints();
if(!cs.isEmpty()){
QhullPoint furthest= cs.last();
if (cs.size() < 6) {
- os << " - coplanar set(furthest p" << furthest.id(pr.run_id) << "):" << endl;
+ os << " - coplanar set(furthest p" << furthest.id() << "):" << endl;
for(QhullPointSet::iterator i=cs.begin(); i!=cs.end(); ++i){
QhullPoint p= *i;
- os << p.print(pr.run_id, " ");
+ os << p.print(" ");
}
}else if(cs.size()<21){
- os << cs.print(pr.run_id, " - coplanar set:");
+ os << cs.print(" - coplanar set:");
}else{
os << " - coplanar set: " << cs.size() << " points.";
- os << furthest.print(pr.run_id, " Furthest");
+ os << furthest.print(" Furthest");
}
- zinc_(Zdistio);
+ // FIXUP zinc_(Zdistio);
double d= facet.distance(furthest);
os << " furthest distance= " << d << endl; //FIXUP QH11010 %2.2g
}
QhullVertexSet vs= facet.vertices();
if(!vs.isEmpty()){
- os << vs.print(pr.run_id, " - vertices:");
+ os << vs.print(" - vertices:");
}
QhullFacetSet fs= facet.neighborFacets();
fs.selectAll();
if(!fs.isEmpty()){
os << fs.printIdentifiers(" - neighboring facets:");
}
return os;
}//operator<< PrintHeader
-//! Print ridges of facet to stream. Same as qh_printfacetridges [io.c]
-//! If qhRunId==UsingLibQhull::NOqhRunId, does not use qh
+//! Print ridges of facet to stream. Same as qh_printfacetridges [io_r.c]
ostream &
operator<<(ostream &os, const QhullFacet::PrintRidges &pr)
{
const QhullFacet facet= *pr.facet;
facetT *f= facet.getFacetT();
QhullRidgeSet rs= facet.ridges();
if(!rs.isEmpty()){
- if(pr.run_id!=UsingLibQhull::NOqhRunId){
- UsingLibQhull q(pr.run_id);
- // No calls to libqhull
- if(f->visible && qh NEWfacets){
- os << " - ridges(ids may be garbage):";
- for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
- QhullRidge r= *i;
- os << " r" << r.id();
- }
- os << endl;
- }else{
- os << " - ridges:" << endl;
+ if(f->visible && pr.facet->qh()->NEWfacets){
+ os << " - ridges(ids may be garbage):";
+ for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
+ QhullRidge r= *i;
+ os << " r" << r.id();
}
+ os << endl;
}else{
os << " - ridges:" << endl;
}
// Keep track of printed ridges
for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
QhullRidge r= *i;
r.getRidgeT()->seen= false;
}
int ridgeCount= 0;
if(facet.dimension()==3){
for(QhullRidge r= rs.first(); !r.getRidgeT()->seen; r= r.nextRidge3d(facet)){
r.getRidgeT()->seen= true;
- os << r.print(pr.run_id);
+ os << r.print("");
++ridgeCount;
if(!r.hasNextRidge3d(facet)){
break;
}
}
}else {
QhullFacetSet ns(facet.neighborFacets());
for(QhullFacetSet::iterator i=ns.begin(); i!=ns.end(); ++i){
QhullFacet neighbor= *i;
QhullRidgeSet nrs(neighbor.ridges());
for(QhullRidgeSet::iterator j=nrs.begin(); j!=nrs.end(); ++j){
QhullRidge r= *j;
if(r.otherFacet(neighbor)==facet){
r.getRidgeT()->seen= true;
- os << r.print(pr.run_id);
+ os << r.print("");
ridgeCount++;
}
}
}
}
if(ridgeCount!=rs.count()){
os << " - all ridges:";
for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
QhullRidge r= *i;
os << " r" << r.id();
}
os << endl;
}
for(QhullRidgeSet::iterator i=rs.begin(); i!=rs.end(); ++i){
QhullRidge r= *i;
if(!r.getRidgeT()->seen){
- os << r.print(pr.run_id);
+ os << r.print("");
}
}
}
return os;
}//operator<< PrintRidges
// "No conversion" error if defined inline
ostream &
operator<<(ostream &os, QhullFacet &f)
{
- os << f.print(UsingLibQhull::NOqhRunId);
+ os << f.print();
return os;
}//<< QhullFacet
diff --git a/src/libqhullcpp/QhullFacet.h b/src/libqhullcpp/QhullFacet.h
index 124c00d..7cd4b6c 100644
--- a/src/libqhullcpp/QhullFacet.h
+++ b/src/libqhullcpp/QhullFacet.h
@@ -1,155 +1,151 @@
/****************************************************************************
**
-** Copyright (c) 2008-2012 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/QhullFacet.h#7 $$Change: 1464 $
-** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+** Copyright (c) 2008-2014 C.B. Barber. All rights reserved.
+** $Id: //main/2011/qhull/src/libqhullcpp/QhullFacet.h#13 $$Change: 1800 $
+** $DateTime: 2014/12/17 21:46:45 $$Author: bbarber $
**
****************************************************************************/
#ifndef QHULLFACET_H
#define QHULLFACET_H
-#include "Coordinates.h"
#include "QhullHyperplane.h"
#include "QhullPoint.h"
#include "QhullSet.h"
#include "QhullPointSet.h"
extern "C" {
- #include "libqhull/qhull_r.h"
+ #include "libqhullr/qhull_ra.h"
}
-#include
-#include
#include
namespace orgQhull {
-#//ClassRef
+#//!\name Used here
+ class Coordinates;
+ class Qhull;
class QhullFacetSet;
class QhullRidge;
- typedef QhullSet QhullRidgeSet;
class QhullVertex;
class QhullVertexSet;
-#//Types
- //! QhullFacet -- Qhull's facet structure, facetT [libqhull.h], as a C++ class
+#//!\name Defined here
class QhullFacet;
+ typedef QhullSet QhullRidgeSet;
//! A QhullFacet is the C++ equivalent to Qhull's facetT*
class QhullFacet {
+#//!\name Defined here
+public:
+ typedef facetT * base_type; // for QhullVertexSet
+
private:
-#//Fields -- no additions (QhullFacetSet of facetT*)
- facetT *qh_facet; //! May be 0 (!isDefined) for corner cases (e.g., *facetSet.end()==0) and tricoplanarOwner()
+#//!\name Fields -- no additions (QhullFacetSet of facetT*)
+ facetT * qh_facet; //! May be 0 (!isDefined) for corner cases (e.g., *facetSet.end()==0) and tricoplanarOwner()
+ QhullQh * qh_qh; //! qhT
-#//Class objects
+#//!\name Class objects
static facetT s_empty_facet; // needed for shallow copy
public:
-#//Constants
-
-#//Constructors
- QhullFacet() : qh_facet(&s_empty_facet) {}
+#//!\name Constructors
+ explicit QhullFacet(const Qhull &q);
+ QhullFacet(const Qhull &q, facetT *f);
+ explicit QhullFacet(QhullQh *qh) : qh_facet(&s_empty_facet), qh_qh(qh) {}
+ QhullFacet(QhullQh *qh, facetT *f) : qh_facet(f ? f : &s_empty_facet), qh_qh(qh) {}
// Creates an alias. Does not copy QhullFacet. Needed for return by value and parameter passing
- QhullFacet(const QhullFacet &o) : qh_facet(o.qh_facet ? o.qh_facet : &s_empty_facet) {}
+ QhullFacet(const QhullFacet &other) : qh_facet(other.qh_facet ? other.qh_facet : &s_empty_facet), qh_qh(other.qh_qh) {}
// Creates an alias. Does not copy QhullFacet. Needed for vector
- QhullFacet &operator=(const QhullFacet &o) { qh_facet= o.qh_facet ? o.qh_facet : &s_empty_facet; return *this; }
- ~QhullFacet() {}
+ QhullFacet & operator=(const QhullFacet &other) { qh_facet= other.qh_facet ? other.qh_facet : &s_empty_facet; qh_qh= other.qh_qh; return *this; }
+ ~QhullFacet() {}
+
-#//Conversion
- //Implicit conversion from facetT
- QhullFacet(facetT *f) : qh_facet(f ? f : &s_empty_facet) {}
+#//!\name GetSet
+ int dimension() const { return qh_qh->hull_dim; }
+ QhullPoint getCenter() { return getCenter(qh_PRINTpoints); }
+ QhullPoint getCenter(qh_PRINT printFormat);
+ facetT * getBaseT() const { return getFacetT(); } //!< For QhullSet
// Do not define facetT(). It conflicts with return type facetT*
- facetT *getFacetT() const { return qh_facet; }
-
-#//QhullSet
- facetT *getBaseT() const { return getFacetT(); }
-
-#//getSet
- int dimension() const;
- QhullPoint getCenter(int qhRunId) { return getCenter(qhRunId, qh_PRINTpoints); }
- QhullPoint getCenter(int qhRunId, qh_PRINT printFormat);
- QhullHyperplane hyperplane() const { return QhullHyperplane(dimension(), qh_facet->normal, qh_facet->offset); }
- int id() const { return qh_facet ? qh_facet->id : -1; }
- QhullHyperplane innerplane(int qhRunId) const;
+ facetT * getFacetT() const { return qh_facet; }
+ QhullHyperplane hyperplane() const { return QhullHyperplane(qh_qh, dimension(), qh_facet->normal, qh_facet->offset); }
+ countT id() const { return (qh_facet ? qh_facet->id : -1); }
+ QhullHyperplane innerplane() const;
bool isDefined() const { return qh_facet && qh_facet != &s_empty_facet; }
bool isGood() const { return qh_facet && qh_facet->good; }
- bool isSimplicial() const { return qh_facet->simplicial; }
- bool isTopOrient() const { return qh_facet->toporient; }
- bool isTriCoplanar() const { return qh_facet->tricoplanar; }
- bool isUpperDelaunay() const { return qh_facet->upperdelaunay; }
- QhullFacet next() const { return qh_facet->next; }
- bool operator==(const QhullFacet &o) const { return qh_facet==o.qh_facet; }
- bool operator!=(const QhullFacet &o) const { return !operator==(o); }
- QhullHyperplane outerplane(int qhRunId) const;
- QhullFacet previous() const { return qh_facet->previous; }
+ bool isSimplicial() const { return qh_facet && qh_facet->simplicial; }
+ bool isTopOrient() const { return qh_facet && qh_facet->toporient; }
+ bool isTriCoplanar() const { return qh_facet && qh_facet->tricoplanar; }
+ bool isUpperDelaunay() const { return qh_facet && qh_facet->upperdelaunay; }
+ QhullFacet next() const { return QhullFacet(qh_qh, qh_facet->next); }
+ bool operator==(const QhullFacet &other) const { return qh_facet==other.qh_facet; }
+ bool operator!=(const QhullFacet &other) const { return !operator==(other); }
+ QhullHyperplane outerplane() const;
+ QhullFacet previous() const { return QhullFacet(qh_qh, qh_facet->previous); }
+ QhullQh * qh() const { return qh_qh; }
QhullFacet tricoplanarOwner() const;
- QhullPoint voronoiVertex(int qhRunId);
+ QhullPoint voronoiVertex();
-#//value
+#//!\name value
//! Undefined if c.size() != dimension()
double distance(const Coordinates &c) const { return distance(c.data()); }
- double distance(const pointT *p) const { return distance(QhullPoint(dimension(), const_cast(p))); }
+ double distance(const pointT *p) const { return distance(QhullPoint(qh_qh, const_cast(p))); }
double distance(const QhullPoint &p) const { return hyperplane().distance(p); }
- double facetArea(int qhRunId);
+ double facetArea();
-#//foreach
+#//!\name foreach
// Can not inline. Otherwise circular reference
QhullPointSet coplanarPoints() const;
QhullFacetSet neighborFacets() const;
QhullPointSet outsidePoints() const;
QhullRidgeSet ridges() const;
QhullVertexSet vertices() const;
-#//IO
+#//!\name IO
struct PrintCenter{
- QhullFacet *facet; // non-const due to facet.center()
- const char *message;
- int run_id;
+ QhullFacet * facet; // non-const due to facet.center()
+ const char * message;
qh_PRINT print_format;
- PrintCenter(int qhRunId, QhullFacet &f, qh_PRINT printFormat, const char * s) : facet(&f), message(s), run_id(qhRunId), print_format(printFormat){}
+ PrintCenter(QhullFacet &f, qh_PRINT printFormat, const char * s) : facet(&f), message(s), print_format(printFormat){}
};//PrintCenter
- PrintCenter printCenter(int qhRunId, qh_PRINT printFormat, const char *message) { return PrintCenter(qhRunId, *this, printFormat, message); }
+ PrintCenter printCenter(qh_PRINT printFormat, const char *message) { return PrintCenter(*this, printFormat, message); }
struct PrintFacet{
- QhullFacet *facet; // non-const due to f->center()
- int run_id;
- PrintFacet(int qhRunId, QhullFacet &f) : facet(&f), run_id(qhRunId) {}
+ QhullFacet * facet; // non-const due to f->center()
+ explicit PrintFacet(QhullFacet &f) : facet(&f) {}
};//PrintFacet
- PrintFacet print(int qhRunId) { return PrintFacet(qhRunId, *this); }
+ PrintFacet print() { return PrintFacet(*this); }
struct PrintFlags{
const QhullFacet *facet;
- const char *message;
+ const char * message;
PrintFlags(const QhullFacet &f, const char *s) : facet(&f), message(s) {}
};//PrintFlags
PrintFlags printFlags(const char *message) const { return PrintFlags(*this, message); }
struct PrintHeader{
- QhullFacet *facet; // non-const due to f->center()
- int run_id;
- PrintHeader(int qhRunId, QhullFacet &f) : facet(&f), run_id(qhRunId) {}
+ QhullFacet * facet; // non-const due to f->center()
+ PrintHeader(QhullFacet &f) : facet(&f) {}
};//PrintHeader
- PrintHeader printHeader(int qhRunId) { return PrintHeader(qhRunId, *this); }
+ PrintHeader printHeader() { return PrintHeader(*this); }
struct PrintRidges{
const QhullFacet *facet;
- int run_id;
- PrintRidges(int qhRunId, QhullFacet &f) : facet(&f), run_id(qhRunId) {}
+ PrintRidges(QhullFacet &f) : facet(&f) {}
};//PrintRidges
- PrintRidges printRidges(int qhRunId) { return PrintRidges(qhRunId, *this); }
+ PrintRidges printRidges() { return PrintRidges(*this); }
};//class QhullFacet
}//namespace orgQhull
-#//Global functions
+#//!\name Global
std::ostream &operator<<(std::ostream &os, const orgQhull::QhullFacet::PrintCenter &pr);
std::ostream &operator<<(std::ostream &os, const orgQhull::QhullFacet::PrintFlags &pr);
std::ostream &operator<<(std::ostream &os, const orgQhull::QhullFacet::PrintHeader &pr);
std::ostream &operator<<(std::ostream &os, const orgQhull::QhullFacet::PrintRidges &pr);
std::ostream &operator<<(std::ostream &os, const orgQhull::QhullFacet::PrintFacet &pr);
std::ostream &operator<<(std::ostream &os, orgQhull::QhullFacet &f); // non-const due to qh_getcenter()
#endif // QHULLFACET_H
diff --git a/src/libqhullcpp/QhullFacetList.cpp b/src/libqhullcpp/QhullFacetList.cpp
index b518b1a..cbd3b64 100644
--- a/src/libqhullcpp/QhullFacetList.cpp
+++ b/src/libqhullcpp/QhullFacetList.cpp
@@ -1,164 +1,172 @@
/****************************************************************************
**
** Copyright (c) 2008-2014 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/QhullFacetList.cpp#3 $$Change: 1464 $
-** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+** $Id: //main/2011/qhull/src/libqhullcpp/QhullFacetList.cpp#7 $$Change: 1797 $
+** $DateTime: 2014/12/15 17:23:41 $$Author: bbarber $
**
****************************************************************************/
#//! QhullFacetList -- Qhull's linked facets, as a C++ class
#include "QhullFacet.h"
#include "QhullFacetList.h"
#include "QhullPoint.h"
#include "QhullRidge.h"
#include "QhullVertex.h"
using std::string;
using std::vector;
#ifdef _MSC_VER // Microsoft Visual C++ -- warning level 4
#pragma warning( disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
#pragma warning( disable : 4996) // function was declared deprecated(strcpy, localtime, etc.)
#endif
namespace orgQhull {
-#//Conversion
+#//!\name Constructors
+
+QhullFacetList::
+QhullFacetList(const Qhull &q, facetT *b, facetT *e )
+: QhullLinkedList(QhullFacet(q, b), QhullFacet(q, e))
+, select_all(false)
+{
+}
+
+#//!\name Conversions
// See qt_qhull.cpp for QList conversions
#ifndef QHULL_NO_STL
std::vector QhullFacetList::
toStdVector() const
{
QhullLinkedListIterator i(*this);
std::vector vs;
while(i.hasNext()){
QhullFacet f= i.next();
if(isSelectAll() || f.isGood()){
vs.push_back(f);
}
}
return vs;
}//toStdVector
#endif //QHULL_NO_STL
#ifndef QHULL_NO_STL
//! Same as PrintVertices
std::vector QhullFacetList::
-vertices_toStdVector(int qhRunId) const
+vertices_toStdVector() const
{
std::vector vs;
- QhullVertexSet qvs(qhRunId, first().getFacetT(), NULL, isSelectAll());
+ QhullVertexSet qvs(qh(), first().getFacetT(), 0, isSelectAll());
for(QhullVertexSet::iterator i=qvs.begin(); i!=qvs.end(); ++i){
vs.push_back(*i);
}
return vs;
}//vertices_toStdVector
#endif //QHULL_NO_STL
-#//Read-only
+#//!\name GetSet
bool QhullFacetList::
contains(const QhullFacet &facet) const
{
if(isSelectAll()){
return QhullLinkedList::contains(facet);
}
for(QhullFacetList::const_iterator i=begin(); i != end(); ++i){
QhullFacet f= *i;
if(f==facet && f.isGood()){
return true;
}
}
return false;
}//contains
int QhullFacetList::
count() const
{
if(isSelectAll()){
return QhullLinkedList::count();
}
int counter= 0;
for(QhullFacetList::const_iterator i=begin(); i != end(); ++i){
if((*i).isGood()){
counter++;
}
}
return counter;
}//count
int QhullFacetList::
count(const QhullFacet &facet) const
{
if(isSelectAll()){
return QhullLinkedList::count(facet);
}
int counter= 0;
for(QhullFacetList::const_iterator i=begin(); i != end(); ++i){
QhullFacet f= *i;
if(f==facet && f.isGood()){
counter++;
}
}
return counter;
}//count
}//namespace orgQhull
-#//Global functions
+#//!\name Global functions
using std::endl;
using std::ostream;
using orgQhull::QhullFacet;
using orgQhull::QhullFacetList;
using orgQhull::QhullVertex;
using orgQhull::QhullVertexSet;
-using orgQhull::UsingLibQhull;
ostream &
operator<<(ostream &os, const QhullFacetList::PrintFacetList &pr)
{
QhullFacetList fs= *pr.facet_list;
os << "Vertices for " << fs.count() << " facets" << endl;
- os << fs.printVertices(pr.run_id);
- os << fs.printFacets(pr.run_id);
+ os << fs.printVertices();
+ os << fs.printFacets();
return os;
}//operator<<
-//! Print facet list to stream. From qh_printafacet [io.c]
+//! Print facet list to stream. From qh_printafacet [io_r.c]
ostream &
operator<<(ostream &os, const QhullFacetList::PrintFacets &pr)
{
for(QhullFacetList::const_iterator i= pr.facet_list->begin(); i != pr.facet_list->end(); ++i){
QhullFacet f= *i;
if(pr.facet_list->isSelectAll() || f.isGood()){
- os << f.print(pr.run_id);
+ os << f.print();
}
}
return os;
}//printFacets
-//! Print vertices of good faces in facet list to stream. From qh_printvertexlist [io.c]
+//! Print vertices of good faces in facet list to stream. From qh_printvertexlist [io_r.c]
//! Same as vertices_toStdVector
ostream &
operator<<(ostream &os, const QhullFacetList::PrintVertices &pr)
{
- QhullVertexSet vs(pr.run_id, pr.facet_list->first().getFacetT(), NULL, pr.facet_list->isSelectAll());
+ QhullVertexSet vs(pr.facet_list->qh(), pr.facet_list->first().getFacetT(), NULL, pr.facet_list->isSelectAll());
for(QhullVertexSet::iterator i=vs.begin(); i!=vs.end(); ++i){
QhullVertex v= *i;
- os << v.print(pr.run_id);
+ os << v.print("");
}
return os;
}//printVertices
std::ostream &
operator<<(ostream &os, const QhullFacetList &fs)
{
- os << fs.printFacets(UsingLibQhull::NOqhRunId);
+ os << fs.printFacets();
return os;
}//QhullFacetList
diff --git a/src/libqhullcpp/QhullFacetList.h b/src/libqhullcpp/QhullFacetList.h
index 46664f3..4b6bb64 100644
--- a/src/libqhullcpp/QhullFacetList.h
+++ b/src/libqhullcpp/QhullFacetList.h
@@ -1,102 +1,104 @@
/****************************************************************************
**
-** Copyright (c) 2008-2012 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/QhullFacetList.h#3 $$Change: 1464 $
-** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+** Copyright (c) 2008-2014 C.B. Barber. All rights reserved.
+** $Id: //main/2011/qhull/src/libqhullcpp/QhullFacetList.h#9 $$Change: 1797 $
+** $DateTime: 2014/12/15 17:23:41 $$Author: bbarber $
**
****************************************************************************/
#ifndef QHULLFACETLIST_H
#define QHULLFACETLIST_H
#include "QhullLinkedList.h"
#include "QhullFacet.h"
#include
+#ifndef QHULL_NO_STL
+#include
+#endif
+
namespace orgQhull {
-#//ClassRef
- class QhullFacet;
+#//!\name Used here
+ class Qhull;
+ class QhullFacet;
+ class QhullQh;
-#//Types
+#//!\name Defined here
//! QhullFacetList -- List of Qhull facets, as a C++ class. See QhullFacetSet.h
- class QhullFacetList;
+ class QhullFacetList;
//! QhullFacetListIterator -- if(f.isGood()){ ... }
- typedef QhullLinkedListIterator
- QhullFacetListIterator;
+ typedef QhullLinkedListIterator QhullFacetListIterator;
class QhullFacetList : public QhullLinkedList {
-#// Fields
+#//!\name Fields
private:
bool select_all; //! True if include bad facets. Default is false.
-#//Constructors
+#//!\name Constructors
public:
+ QhullFacetList(const Qhull &q, facetT *b, facetT *e);
+ QhullFacetList(QhullQh *qh, facetT *b, facetT *e);
QhullFacetList(QhullFacet b, QhullFacet e) : QhullLinkedList(b, e), select_all(false) {}
//Copy constructor copies pointer but not contents. Needed for return by value and parameter passing.
- QhullFacetList(const QhullFacetList &o) : QhullLinkedList(*o.begin(), *o.end()), select_all(o.select_all) {}
- ~QhullFacetList() {}
+ QhullFacetList(const QhullFacetList &other) : QhullLinkedList(*other.begin(), *other.end()), select_all(other.select_all) {}
+ QhullFacetList & operator=(const QhullFacetList &other) { QhullLinkedList::operator =(other); select_all= other.select_all; }
+ ~QhullFacetList() {}
-private:
- //!Disable default constructor and copy assignment. See QhullLinkedList
+private: //!Disable default constructor. See QhullLinkedList
QhullFacetList();
- QhullFacetList &operator=(const QhullFacetList &);
public:
-#//Conversion
+#//!\name Conversion
#ifndef QHULL_NO_STL
std::vector toStdVector() const;
- std::vector vertices_toStdVector(int qhRunId) const;
+ std::vector vertices_toStdVector() const;
#endif //QHULL_NO_STL
#ifdef QHULL_USES_QT
QList toQList() const;
- QList vertices_toQList(int qhRunId) const;
+ QList vertices_toQList() const;
#endif //QHULL_USES_QT
-#//GetSet
+#//!\name GetSet
+ //! Filtered by facet.isGood(). May be 0 when !isEmpty().
+ countT count() const;
+ bool contains(const QhullFacet &f) const;
+ countT count(const QhullFacet &f) const;
bool isSelectAll() const { return select_all; }
+ QhullQh * qh() const { return first().qh(); }
void selectAll() { select_all= true; }
void selectGood() { select_all= false; }
+ //!< operator==() does not depend on isGood()
-#//Read-only
- //! Filtered by facet.isGood(). May be 0 when !isEmpty().
- int count() const;
- bool contains(const QhullFacet &f) const;
- int count(const QhullFacet &f) const;
- //! operator==() does not depend on isGood()
-
-#//IO
+#//!\name IO
struct PrintFacetList{
const QhullFacetList *facet_list;
- int run_id;
- PrintFacetList(int qhRunId, const QhullFacetList &fl) : facet_list(&fl), run_id(qhRunId) {}
+ PrintFacetList(const QhullFacetList &fl) : facet_list(&fl) {}
};//PrintFacetList
- PrintFacetList print(int qhRunId) const { return PrintFacetList(qhRunId, *this); }
+ PrintFacetList print() const { return PrintFacetList(*this); }
struct PrintFacets{
const QhullFacetList *facet_list;
- int run_id;
- PrintFacets(int qhRunId, const QhullFacetList &fl) : facet_list(&fl), run_id(qhRunId) {}
+ PrintFacets(const QhullFacetList &fl) : facet_list(&fl) {}
};//PrintFacets
- PrintFacets printFacets(int qhRunId) const { return PrintFacets(qhRunId, *this); }
+ PrintFacets printFacets() const { return PrintFacets(*this); }
struct PrintVertices{
const QhullFacetList *facet_list;
- int run_id; //! Can not be NOrunId due to qh_facetvertices
- PrintVertices(int qhRunId, const QhullFacetList &fl) : facet_list(&fl), run_id(qhRunId) {}
+ PrintVertices(const QhullFacetList &fl) : facet_list(&fl) {}
};//PrintVertices
- PrintVertices printVertices(int qhRunId) const { return PrintVertices(qhRunId, *this); }
+ PrintVertices printVertices() const { return PrintVertices(*this); }
};//class QhullFacetList
}//namespace orgQhull
-#//== Global namespace =========================================
+#//!\name == Global namespace =========================================
std::ostream &operator<<(std::ostream &os, const orgQhull::QhullFacetList::PrintFacetList &p);
std::ostream &operator<<(std::ostream &os, const orgQhull::QhullFacetList::PrintFacets &p);
std::ostream &operator<<(std::ostream &os, const orgQhull::QhullFacetList::PrintVertices &p);
std::ostream &operator<<(std::ostream &os, const orgQhull::QhullFacetList &fs);
#endif // QHULLFACETLIST_H
diff --git a/src/libqhullcpp/QhullFacetSet.cpp b/src/libqhullcpp/QhullFacetSet.cpp
index 3bb80f7..411b730 100644
--- a/src/libqhullcpp/QhullFacetSet.cpp
+++ b/src/libqhullcpp/QhullFacetSet.cpp
@@ -1,145 +1,147 @@
/****************************************************************************
**
** Copyright (c) 2008-2014 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/QhullFacetSet.cpp#5 $$Change: 1464 $
-** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+** $Id: //main/2011/qhull/src/libqhullcpp/QhullFacetSet.cpp#10 $$Change: 1800 $
+** $DateTime: 2014/12/17 21:46:45 $$Author: bbarber $
**
****************************************************************************/
#//! QhullFacetSet -- Qhull's linked facets, as a C++ class
-#include "QhullFacet.h"
#include "QhullFacetSet.h"
+
+#include "QhullFacet.h" // Before QhullFacetSet for base_type
#include "QhullPoint.h"
#include "QhullRidge.h"
#include "QhullVertex.h"
-using std::string;
+#ifndef QHULL_NO_STL
using std::vector;
+#endif
#ifdef _MSC_VER // Microsoft Visual C++ -- warning level 4
#pragma warning( disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
#pragma warning( disable : 4996) // function was declared deprecated(strcpy, localtime, etc.)
#endif
namespace orgQhull {
-#//Conversion
+#//!\name Conversions
// See qt-qhull.cpp for QList conversions
#ifndef QHULL_NO_STL
std::vector QhullFacetSet::
toStdVector() const
{
QhullSetIterator i(*this);
std::vector vs;
while(i.hasNext()){
QhullFacet f= i.next();
if(isSelectAll() || f.isGood()){
vs.push_back(f);
}
}
return vs;
}//toStdVector
#endif //QHULL_NO_STL
-#//Read-only
+#//!\name GetSet
bool QhullFacetSet::
contains(const QhullFacet &facet) const
{
if(isSelectAll()){
return QhullSet::contains(facet);
}
for(QhullFacetSet::const_iterator i=begin(); i != end(); ++i){
QhullFacet f= *i;
if(f==facet && f.isGood()){
return true;
}
}
return false;
}//contains
int QhullFacetSet::
count() const
{
if(isSelectAll()){
return QhullSet::count();
}
int counter= 0;
for(QhullFacetSet::const_iterator i=begin(); i != end(); ++i){
QhullFacet f= *i;
if(f.isGood()){
counter++;
}
}
return counter;
}//count
int QhullFacetSet::
count(const QhullFacet &facet) const
{
if(isSelectAll()){
return QhullSet::count(facet);
}
int counter= 0;
for(QhullFacetSet::const_iterator i=begin(); i != end(); ++i){
QhullFacet f= *i;
if(f==facet && f.isGood()){
counter++;
}
}
return counter;
}//count
}//namespace orgQhull
-#//Global functions
+#//!\name Global functions
using std::endl;
using std::ostream;
using orgQhull::QhullFacet;
using orgQhull::QhullFacetSet;
-using orgQhull::UsingLibQhull;
ostream &
operator<<(ostream &os, const QhullFacetSet &fs)
{
- os << fs.print(UsingLibQhull::NOqhRunId, "");
+ os << fs.print("");
return os;
}//<begin(); i!=p.facet_set->end(); ++i){
const QhullFacet f= *i;
if(f.getFacetT()==qh_MERGEridge){
os << " MERGE";
}else if(f.getFacetT()==qh_DUPLICATEridge){
os << " DUP";
}else if(p.facet_set->isSelectAll() || f.isGood()){
os << " f" << f.id();
}
}
os << endl;
return os;
}//<
namespace orgQhull {
-#//ClassRef
- class QhullFacet;
+#//!\name Used here
+ class Qhull;
-#//Types
+#//!\name Defined here
//! QhullFacetSet -- a set of Qhull facets, as a C++ class. See QhullFacetList.h
- class QhullFacetSet;
- typedef QhullSetIterator
- QhullFacetSetIterator;
+ class QhullFacetSet;
+ typedef QhullSetIterator QhullFacetSetIterator;
class QhullFacetSet : public QhullSet {
+#//!\name Defined here
+public:
+ typedef facetT * base_type; // for QhullVertexSet
+
private:
-#//Fields
+#//!\name Fields
bool select_all; //! True if include bad facets. Default is false.
public:
-#//Constructor
+#//!\name Constructor
//Conversion from setT* is not type-safe. Implicit conversion for void* to T
- explicit QhullFacetSet(setT *s) : QhullSet(s), select_all(false) {}
+ QhullFacetSet(const Qhull &q, setT *s) : QhullSet(q, s), select_all(false) {}
+ QhullFacetSet(QhullQh *qh, setT *s) : QhullSet(qh, s), select_all(false) {}
//Copy constructor copies pointer but not contents. Needed for return by value and parameter passing.
- QhullFacetSet(const QhullFacetSet &o) : QhullSet(o), select_all(o.select_all) {}
+ QhullFacetSet(const QhullFacetSet &other) : QhullSet(other), select_all(other.select_all) {}
+ QhullFacetSet & operator=(const QhullFacetSet &other) { QhullSet::operator=(other); select_all= other.select_all; }
private:
- //!Disable default constructor and copy assignment. See QhullSetBase
+ //!Disable default constructor. See QhullSetBase
QhullFacetSet();
- QhullFacetSet &operator=(const QhullFacetSet &);
public:
-#//Conversion
+#//!\name Conversion
#ifndef QHULL_NO_STL
std::vector toStdVector() const;
#endif //QHULL_NO_STL
#ifdef QHULL_USES_QT
QList toQList() const;
#endif //QHULL_USES_QT
-#//GetSet
- bool isSelectAll() const { return select_all; }
- void selectAll() { select_all= true; }
- void selectGood() { select_all= false; }
-
-#//Read-only
+#//!\name GetSet
//! Filtered by facet.isGood(). May be 0 when !isEmpty().
- int count() const;
+ countT count() const;
bool contains(const QhullFacet &f) const;
- int count(const QhullFacet &f) const;
+ countT count(const QhullFacet &f) const;
+ bool isSelectAll() const { return select_all; }
//! operator==() does not depend on isGood()
+ void selectAll() { select_all= true; }
+ void selectGood() { select_all= false; }
-#//IO
+#//!\name IO
// Not same as QhullFacetList#IO. A QhullFacetSet is a component of a QhullFacetList.
struct PrintFacetSet{
const QhullFacetSet *facet_set;
- const char *print_message;
- int run_id;
- PrintFacetSet(int qhRunId, const char *message, const QhullFacetSet *s) : facet_set(s), print_message(message), run_id(qhRunId) {}
+ const char * print_message;
+ PrintFacetSet(const char *message, const QhullFacetSet *s) : facet_set(s), print_message(message) {}
};//PrintFacetSet
- const PrintFacetSet print(int qhRunId, const char *message) const { return PrintFacetSet(qhRunId, message, this); }
+ const PrintFacetSet print(const char *message) const { return PrintFacetSet(message, this); }
struct PrintIdentifiers{
const QhullFacetSet *facet_set;
- const char *print_message;
+ const char * print_message;
PrintIdentifiers(const char *message, const QhullFacetSet *s) : facet_set(s), print_message(message) {}
};//PrintIdentifiers
PrintIdentifiers printIdentifiers(const char *message) const { return PrintIdentifiers(message, this); }
};//class QhullFacetSet
}//namespace orgQhull
-#//== Global namespace =========================================
+#//!\name == Global namespace =========================================
std::ostream &operator<<(std::ostream &os, const orgQhull::QhullFacetSet &fs);
std::ostream &operator<<(std::ostream &os, const orgQhull::QhullFacetSet::PrintFacetSet &pr);
std::ostream &operator<<(std::ostream &os, const orgQhull::QhullFacetSet::PrintIdentifiers &p);
#endif // QHULLFACETSET_H
diff --git a/src/libqhullcpp/QhullHyperplane.cpp b/src/libqhullcpp/QhullHyperplane.cpp
index c1f0925..0a6f51f 100644
--- a/src/libqhullcpp/QhullHyperplane.cpp
+++ b/src/libqhullcpp/QhullHyperplane.cpp
@@ -1,166 +1,185 @@
/****************************************************************************
**
** Copyright (c) 2009-2014 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/QhullHyperplane.cpp#6 $$Change: 1464 $
-** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+** $Id: //main/2011/qhull/src/libqhullcpp/QhullHyperplane.cpp#10 $$Change: 1797 $
+** $DateTime: 2014/12/15 17:23:41 $$Author: bbarber $
**
****************************************************************************/
#include "QhullHyperplane.h"
+
+#include "Qhull.h"
#include "QhullPoint.h"
#include
#ifdef _MSC_VER // Microsoft Visual C++ -- warning level 4
#endif
namespace orgQhull {
-#//Conversion
+#//!\name Constructors
+
+QhullHyperplane::
+QhullHyperplane(const Qhull &q)
+: hyperplane_coordinates(0)
+, hyperplane_dimension(0)
+, hyperplane_offset(0.0)
+, qh_qh(q.qh())
+{
+}
+
+QhullHyperplane::
+QhullHyperplane(const Qhull &q, int hyperplaneDimension, coordT *c, coordT hyperplaneOffset)
+: hyperplane_coordinates(c)
+, hyperplane_dimension(hyperplaneDimension)
+, hyperplane_offset(hyperplaneOffset)
+, qh_qh(q.qh())
+{
+}
+
+#//!\name Conversions
// See qt-qhull.cpp for QList conversions
#ifndef QHULL_NO_STL
std::vector QhullHyperplane::
toStdVector() const
{
QhullHyperplaneIterator i(*this);
std::vector fs;
while(i.hasNext()){
fs.push_back(i.next());
}
fs.push_back(hyperplane_offset);
return fs;
}//toStdVector
#endif //QHULL_NO_STL
-#//Value
+#//!\name GetSet
+
+bool QhullHyperplane::
+operator==(const QhullHyperplane &other) const
+{
+ if(hyperplane_dimension!=other.hyperplane_dimension){
+ return false;
+ }
+ double d= fabs(hyperplane_offset-other.hyperplane_offset);
+ if(d>qh_qh->distanceEpsilon()){
+ return false;
+ }
+ const coordT *c= hyperplane_coordinates;
+ const coordT *c2= other.hyperplane_coordinates;
+ if(c==c2){
+ return true;
+ }
+ double dist2= 0.0;
+ for(int k= hyperplane_dimension; k--; ){
+ double diff= *c++ - *c2++;
+ dist2 += diff*diff;
+ }
+ if(dist2 > qh_qh->angleEpsilon()){
+ return false;
+ }
+ return true;
+}//operator==
+
+#//!\name Methods
//! Return distance from point to hyperplane.
//! If greater than zero, the point is above the facet (i.e., outside).
-// qh_distplane [geom.c], QhullFacet::distance, and QhullHyperplane::distance are copies
+// qh_distplane [geom_r.c], QhullFacet::distance, and QhullHyperplane::distance are copies
// Does not support RANDOMdist or logging
double QhullHyperplane::
distance(const QhullPoint &p) const
{
const coordT *point= p.coordinates();
int dim= p.dimension();
QHULL_ASSERT(dim==dimension());
const coordT *normal= coordinates();
double dist;
switch (dim){
case 2:
dist= offset() + point[0] * normal[0] + point[1] * normal[1];
break;
case 3:
dist= offset() + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2];
break;
case 4:
dist= offset()+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3];
break;
case 5:
dist= offset()+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4];
break;
case 6:
dist= offset()+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5];
break;
case 7:
dist= offset()+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6];
break;
case 8:
dist= offset()+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6]+point[7]*normal[7];
break;
default:
dist= offset();
for (int k=dim; k--; )
dist += *point++ * *normal++;
break;
}
return dist;
}//distance
double QhullHyperplane::
norm() const {
double d= 0.0;
const coordT *c= coordinates();
for (int k=dimension(); k--; ){
d += *c * *c;
++c;
}
return sqrt(d);
}//norm
-#//Operator
-
-bool QhullHyperplane::
-operator==(const QhullHyperplane &other) const
-{
- if(hyperplane_dimension!=other.hyperplane_dimension){
- return false;
- }
- double d= fabs(hyperplane_offset-other.hyperplane_offset);
- if(d>UsingLibQhull::globalDistanceEpsilon()){
- return false;
- }
- const coordT *c= hyperplane_coordinates;
- const coordT *c2= other.hyperplane_coordinates;
- if(c==c2){
- return true;
- }
- double dist2= 0.0;
- for(int k= hyperplane_dimension; k--; ){
- double diff= *c++ - *c2++;
- dist2 += diff*diff;
- }
- if(dist2 > UsingLibQhull::globalAngleEpsilon()){
- return false;
- }
- return true;
-}//operator==
-
-#//GetSet
-
}//namespace orgQhull
-#//Global functions
+#//!\name Global functions
using std::ostream;
using orgQhull::QhullHyperplane;
-using orgQhull::UsingLibQhull;
-#//operator<<
+#//!\name GetSet<<
ostream &
operator<<(ostream &os, const QhullHyperplane &p)
{
os << p.print();
return os;
}
ostream &
operator<<(ostream &os, const QhullHyperplane::PrintHyperplane &pr)
{
- QhullHyperplane p= *pr.hyperplane;
if(pr.print_message){
os << pr.print_message;
}
+ QhullHyperplane p= *pr.hyperplane;
const realT *c= p.coordinates();
for(int k=p.dimension(); k--; ){
realT r= *c++;
if(pr.print_message){
os << " " << r; // FIXUP QH11010 %8.4g
}else{
os << " " << r; // FIXUP QH11010 qh_REAL_1
}
}
if(pr.hyperplane_offset_message){
os << pr.hyperplane_offset_message << " " << p.offset();
}else{
os << " " << p.offset();
}
os << std::endl;
return os;
}//PrintHyperplane
diff --git a/src/libqhullcpp/QhullHyperplane.h b/src/libqhullcpp/QhullHyperplane.h
index b2ee895..eaad842 100644
--- a/src/libqhullcpp/QhullHyperplane.h
+++ b/src/libqhullcpp/QhullHyperplane.h
@@ -1,122 +1,123 @@
/****************************************************************************
**
-** Copyright (c) 2009-2012 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/QhullHyperplane.h#6 $$Change: 1464 $
-** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+** Copyright (c) 2009-2014 C.B. Barber. All rights reserved.
+** $Id: //main/2011/qhull/src/libqhullcpp/QhullHyperplane.h#11 $$Change: 1797 $
+** $DateTime: 2014/12/15 17:23:41 $$Author: bbarber $
**
****************************************************************************/
#ifndef QHHYPERPLANE_H
#define QHHYPERPLANE_H
#include "QhullError.h"
#include "QhullIterator.h"
-#include "UsingLibQhull.h"
+#include "QhullQh.h"
extern "C" {
- #include "libqhull/qhull_r.h"
+ #include "libqhullr/qhull_ra.h"
}
#include
namespace orgQhull {
-#//ClassRef
+
+#//!\name Used here
+ class Qhull;
class QhullPoint;
-#//Types
+#//!\name Defined here
//! QhullHyperplane as an offset, dimension, and pointer to coordinates
class QhullHyperplane;
//! Java-style iterator for QhullHyperplane coordinates
class QhullHyperplaneIterator;
class QhullHyperplane { // Similar to QhullPoint
-
-private:
-#//Fields
- coordT *hyperplane_coordinates; // Keep pointers aligned
- int hyperplane_dimension;
- coordT hyperplane_offset;
-
public:
-#//Subtypes
+#//!\name Subtypes
typedef const coordT * iterator;
typedef const coordT * const_iterator;
typedef QhullHyperplane::iterator Iterator;
typedef QhullHyperplane::const_iterator ConstIterator;
-#//Construct
- QhullHyperplane() : hyperplane_coordinates(0), hyperplane_dimension(0), hyperplane_offset(0.0) {};
- QhullHyperplane(int hyperplaneDimension, coordT *c, coordT hyperplaneOffset) : hyperplane_coordinates(c), hyperplane_dimension(hyperplaneDimension), hyperplane_offset(hyperplaneOffset) {}
+private:
+#//!\name Fields
+ coordT * hyperplane_coordinates; // Keep pointers aligned
+ int hyperplane_dimension;
+ coordT hyperplane_offset;
+ QhullQh * qh_qh;
+
+#//!\name Construct
+public:
+ QhullHyperplane(const Qhull &q);
+ QhullHyperplane(const Qhull &q, int hyperplaneDimension, coordT *c, coordT hyperplaneOffset);
+ QhullHyperplane(QhullQh *qh) : hyperplane_coordinates(0), hyperplane_dimension(0), hyperplane_offset(0.0), qh_qh(qh) {}
+ QhullHyperplane(QhullQh *qh, int hyperplaneDimension, coordT *c, coordT hyperplaneOffset) : hyperplane_coordinates(c), hyperplane_dimension(hyperplaneDimension), hyperplane_offset(hyperplaneOffset), qh_qh(qh) {}
// Creates an alias. Does not copy the hyperplane's coordinates. Needed for return by value and parameter passing.
- QhullHyperplane(const QhullHyperplane &other) : hyperplane_coordinates(other.hyperplane_coordinates), hyperplane_dimension(other.hyperplane_dimension), hyperplane_offset(other.hyperplane_offset) {}
+ QhullHyperplane(const QhullHyperplane &other) : hyperplane_coordinates(other.hyperplane_coordinates), hyperplane_dimension(other.hyperplane_dimension), hyperplane_offset(other.hyperplane_offset), qh_qh(other.qh_qh) {}
// Creates an alias. Does not copy the hyperplane's coordinates. Needed for vector
- QhullHyperplane &operator=(const QhullHyperplane &other) { hyperplane_coordinates= other.hyperplane_coordinates; hyperplane_dimension= other.hyperplane_dimension; hyperplane_offset= other.hyperplane_offset; return *this; }
- ~QhullHyperplane() {}
+ QhullHyperplane & operator=(const QhullHyperplane &other) { hyperplane_coordinates= other.hyperplane_coordinates; hyperplane_dimension= other.hyperplane_dimension; hyperplane_offset= other.hyperplane_offset; qh_qh= other.qh_qh; return *this; }
+ ~QhullHyperplane() {}
-#//Conversions --
+#//!\name Conversions --
//! Includes offset at end
#ifndef QHULL_NO_STL
std::vector toStdVector() const;
#endif //QHULL_NO_STL
#ifdef QHULL_USES_QT
QList toQList() const;
#endif //QHULL_USES_QT
-#//Read-only
+#//!\name GetSet
public:
- const coordT *coordinates() const { return hyperplane_coordinates; }
- coordT *coordinates() { return hyperplane_coordinates; }
+ const coordT * coordinates() const { return hyperplane_coordinates; }
+ coordT * coordinates() { return hyperplane_coordinates; }
+ void defineAs(int hyperplaneDimension, coordT *c, coordT hyperplaneOffset) { QHULL_ASSERT(hyperplaneDimension>=0); hyperplane_coordinates= c; hyperplane_dimension= hyperplaneDimension; hyperplane_offset= hyperplaneOffset; }
+ //! Creates an alias to other using the same qh_qh
+ void defineAs(QhullHyperplane &other) { hyperplane_coordinates= other.coordinates(); hyperplane_dimension= other.dimension(); hyperplane_offset= other.offset(); }
int dimension() const { return hyperplane_dimension; }
bool isDefined() const { return hyperplane_coordinates!=0 && hyperplane_dimension>0; }
coordT offset() const { return hyperplane_offset; }
-
-#//Define
- void defineAs(int hyperplaneDimension, coordT *c, coordT hyperplaneOffset) { QHULL_ASSERT(hyperplaneDimension>=0); hyperplane_coordinates= c; hyperplane_dimension= hyperplaneDimension; hyperplane_offset= hyperplaneOffset; }
- //! Creates an alias to other
- void defineAs(QhullHyperplane &other) { hyperplane_coordinates= other.coordinates(); hyperplane_dimension= other.dimension(); hyperplane_offset= other.offset(); }
+ bool operator==(const QhullHyperplane &other) const;
+ bool operator!=(const QhullHyperplane &other) const { return !operator==(other); }
+ const coordT & operator[](int idx) const { QHULL_ASSERT(idx>=0 && idx=0 && idx=0 && idx=0 && idx
#include
#include
//! Avoid dependence on
namespace std { struct bidirectional_iterator_tag; struct random_access_iterator_tag; }
namespace orgQhull {
-#//Defined here
+#//!\name Defined here
//! QHULL_DECLARE_SEQUENTIAL_ITERATOR(C) -- Declare a Java-style iterator
//! QHULL_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(C) -- Declare a mutable Java-style iterator
//! QHULL_DECLARE_SET_ITERATOR(C) -- Declare a set iterator
//! QHULL_DECLARE_MUTABLE_SET_ITERATOR(C) -- Declare a mutable set iterator
- //! Derived from Qt/core/tools/qiterator.h and qset.h/FOREACHsetelement_()
+ //! Derived from Qt/core/tools/qiterator.h and qset_r.h/FOREACHsetelement_()
// Changed c to C* as in Mutable... Assumes c does not go away.
#define QHULL_DECLARE_SEQUENTIAL_ITERATOR(C, T) \
\
class C##Iterator \
{ \
typedef C::const_iterator const_iterator; \
const C *c; \
const_iterator i; \
public: \
inline C##Iterator(const C &container) \
: c(&container), i(c->constBegin()) {} \
inline C##Iterator &operator=(const C &container) \
{ c = &container; i = c->constBegin(); return *this; } \
inline void toFront() { i = c->constBegin(); } \
inline void toBack() { i = c->constEnd(); } \
inline bool hasNext() const { return i != c->constEnd(); } \
inline const T &next() { return *i++; } \
inline const T &peekNext() const { return *i; } \
inline bool hasPrevious() const { return i != c->constBegin(); } \
inline const T &previous() { return *--i; } \
inline const T &peekPrevious() const { const_iterator p = i; return *--p; } \
inline bool findNext(const T &t) \
{ while (i != c->constEnd()) if (*i++ == t) return true; return false; } \
inline bool findPrevious(const T &t) \
{ while (i != c->constBegin()) if (*(--i) == t) return true; \
return false; } \
};//C##Iterator
// Remove setShareable() from Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR
// Uses QHULL_ASSERT (assert.h)
// Duplicated in MutablePointIterator without insert or remove
#define QHULL_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(C, T) \
class Mutable##C##Iterator \
{ \
typedef C::iterator iterator; \
typedef C::const_iterator const_iterator; \
C *c; \
iterator i, n; \
inline bool item_exists() const { return const_iterator(n) != c->constEnd(); } \
public: \
inline Mutable##C##Iterator(C &container) \
: c(&container) \
{ i = c->begin(); n = c->end(); } \
inline ~Mutable##C##Iterator() \
{} \
inline Mutable##C##Iterator &operator=(C &container) \
{ c = &container; \
i = c->begin(); n = c->end(); return *this; } \
inline void toFront() { i = c->begin(); n = c->end(); } \
inline void toBack() { i = c->end(); n = i; } \
inline bool hasNext() const { return c->constEnd() != const_iterator(i); } \
inline T &next() { n = i++; return *n; } \
inline T &peekNext() const { return *i; } \
inline bool hasPrevious() const { return c->constBegin() != const_iterator(i); } \
inline T &previous() { n = --i; return *n; } \
inline T &peekPrevious() const { iterator p = i; return *--p; } \
inline void remove() \
{ if (c->constEnd() != const_iterator(n)) { i = c->erase(n); n = c->end(); } } \
inline void setValue(const T &t) const { if (c->constEnd() != const_iterator(n)) *n = t; } \
inline T &value() { QHULL_ASSERT(item_exists()); return *n; } \
inline const T &value() const { QHULL_ASSERT(item_exists()); return *n; } \
inline void insert(const T &t) { n = i = c->insert(i, t); ++i; } \
inline bool findNext(const T &t) \
{ while (c->constEnd() != const_iterator(n = i)) if (*i++ == t) return true; return false; } \
inline bool findPrevious(const T &t) \
{ while (c->constBegin() != const_iterator(i)) if (*(n = --i) == t) return true; \
n = c->end(); return false; } \
};//Mutable##C##Iterator
#define QHULL_DECLARE_SET_ITERATOR(C) \
\
template \
class Qhull##C##Iterator \
{ \
typedef typename Qhull##C::const_iterator const_iterator; \
Qhull##C c; \
const_iterator i; \
public: \
inline Qhull##C##Iterator(const Qhull##C &container) \
: c(container), i(c.constBegin()) {} \
inline Qhull##C##Iterator &operator=(const Qhull##C &container) \
{ c = container; i = c.constBegin(); return *this; } \
inline void toFront() { i = c.constBegin(); } \
inline void toBack() { i = c.constEnd(); } \
inline bool hasNext() const { return i != c.constEnd(); } \
inline const T &next() { return *i++; } \
inline const T &peekNext() const { return *i; } \
inline bool hasPrevious() const { return i != c.constBegin(); } \
inline const T &previous() { return *--i; } \
inline const T &peekPrevious() const { const_iterator p = i; return *--p; } \
inline bool findNext(const T &t) \
{ while (i != c.constEnd()) if (*i++ == t) return true; return false; } \
inline bool findPrevious(const T &t) \
{ while (i != c.constBegin()) if (*(--i) == t) return true; \
return false; } \
};//Qhull##C##Iterator
#define QHULL_DECLARE_MUTABLE_SET_ITERATOR(C) \
\
template \
class QhullMutable##C##Iterator \
{ \
typedef typename Qhull##C::iterator iterator; \
typedef typename Qhull##C::const_iterator const_iterator; \
Qhull##C *c; \
iterator i, n; \
inline bool item_exists() const { return const_iterator(n) != c->constEnd(); } \
public: \
inline Mutable##C##Iterator(Qhull##C &container) \
: c(&container) \
{ c->setSharable(false); i = c->begin(); n = c->end(); } \
inline ~Mutable##C##Iterator() \
{ c->setSharable(true); } \
inline Mutable##C##Iterator &operator=(Qhull##C &container) \
{ c->setSharable(true); c = &container; c->setSharable(false); \
i = c->begin(); n = c->end(); return *this; } \
inline void toFront() { i = c->begin(); n = c->end(); } \
inline void toBack() { i = c->end(); n = i; } \
inline bool hasNext() const { return c->constEnd() != const_iterator(i); } \
inline T &next() { n = i++; return *n; } \
inline T &peekNext() const { return *i; } \
inline bool hasPrevious() const { return c->constBegin() != const_iterator(i); } \
inline T &previous() { n = --i; return *n; } \
inline T &peekPrevious() const { iterator p = i; return *--p; } \
inline void remove() \
{ if (c->constEnd() != const_iterator(n)) { i = c->erase(n); n = c->end(); } } \
inline void setValue(const T &t) const { if (c->constEnd() != const_iterator(n)) *n = t; } \
inline T &value() { Q_ASSERT(item_exists()); return *n; } \
inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \
inline void insert(const T &t) { n = i = c->insert(i, t); ++i; } \
inline bool findNext(const T &t) \
{ while (c->constEnd() != const_iterator(n = i)) if (*i++ == t) return true; return false; } \
inline bool findPrevious(const T &t) \
{ while (c->constBegin() != const_iterator(i)) if (*(n = --i) == t) return true; \
n = c->end(); return false; } \
};//QhullMutable##C##Iterator
}//namespace orgQhull
#endif // QHULLITERATOR_H
diff --git a/src/libqhullcpp/QhullLinkedList.h b/src/libqhullcpp/QhullLinkedList.h
index 9f05dc9..74b0000 100644
--- a/src/libqhullcpp/QhullLinkedList.h
+++ b/src/libqhullcpp/QhullLinkedList.h
@@ -1,377 +1,380 @@
/****************************************************************************
**
-** Copyright (c) 2008-2012 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/QhullLinkedList.h#3 $$Change: 1464 $
-** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+** Copyright (c) 2008-2014 C.B. Barber. All rights reserved.
+** $Id: //main/2011/qhull/src/libqhullcpp/QhullLinkedList.h#9 $$Change: 1797 $
+** $DateTime: 2014/12/15 17:23:41 $$Author: bbarber $
**
****************************************************************************/
#ifndef QHULLLINKEDLIST_H
#define QHULLLINKEDLIST_H
namespace std { struct bidirectional_iterator_tag; struct random_access_iterator_tag; }
#include "QhullError.h"
+extern "C" {
+ #include "libqhullr/qhull_ra.h"
+}
#ifdef QHULL_USES_QT
#include
#endif
#ifndef QHULL_NO_STL
#include
#endif
namespace orgQhull {
-#//Type
+#//!\name Defined here
//! QhullLinkedList -- A linked list modeled on QLinkedList.
//! T is an opaque type with T(B *b), b=t.getBaseT(), t=t.next(), and t=t.prev(). The end node is a sentinel.
//! libqhull owns the contents.
//! QhullLinkedList does not define erase(), clear(), removeFirst(), removeLast(), pop_back(), pop_front(), fromStdList()
- //! Derived from Qt/core/tools/qlinkedlist.h and libqhull.h/FORALLfacets_()
+ //! Derived from Qt/core/tools/qlinkedlist.h and libqhull_r.h/FORALLfacets_()
//! QhullLinkedList::const_iterator -- STL-style iterator
//! QhullLinkedList::iterator -- STL-style iterator
//! QhullLinkedListIterator -- Java-style iterator
//! Derived from Qt/core/tools/qiterator.h
//! Works with Qt's foreach keyword [Qt/src/corelib/global/qglobal.h]
template
class QhullLinkedList
{
-private:
-#//Fields
- T begin_node;
- T end_node; //! Sentinel node at end of list
-
+#//!\name Defined here
public:
-#//Subtypes and types
- class const_iterator;
- class iterator;
+ class const_iterator;
+ class iterator;
typedef const_iterator ConstIterator;
typedef iterator Iterator;
typedef ptrdiff_t difference_type;
- typedef int size_type;
+ typedef countT size_type;
typedef T value_type;
typedef const value_type *const_pointer;
typedef const value_type &const_reference;
typedef value_type *pointer;
typedef value_type &reference;
-#//Constructors
+#//!\name Fields
+private:
+ T begin_node;
+ T end_node; //! Sentinel node at end of list
+
+#//!\name Constructors
+public:
QhullLinkedList(T b, T e) : begin_node(b), end_node(e) {}
//Copy constructor copies pointer but not contents. Needed for return by value and parameter passing.
- QhullLinkedList(const QhullLinkedList &o) : begin_node(o.begin_node), end_node(o.end_node) {}
- ~QhullLinkedList() {}
+ QhullLinkedList(const QhullLinkedList &other) : begin_node(other.begin_node), end_node(other.end_node) {}
+ QhullLinkedList & operator=(const QhullLinkedList &other) { begin_node= other.begin_node; end_node= other.end_node; }
+ ~QhullLinkedList() {}
private:
//!disabled since a sentinel must be allocated as the private type
QhullLinkedList() {}
//!disabled since qs= qs2 is ambiguous (pointer vs. contents)
- QhullLinkedList &operator=(const QhullLinkedList &l) {}
public:
-#//Conversions
+#//!\name Conversions
#ifndef QHULL_NO_STL
std::vector toStdVector() const;
#endif
#ifdef QHULL_USES_QT
QList toQList() const;
#endif
-#//Read-only
- int count() const;
- //count(t) under #//Search
- bool empty() const { return isEmpty(); }
+#//!\name GetSet
+ countT count() const;
+ //count(t) under #//!\name Search
bool isEmpty() const { return (begin_node==end_node); }
bool operator==(const QhullLinkedList &o) const;
bool operator!=(const QhullLinkedList &o) const { return !operator==(o); }
size_t size() const { return count(); }
-#//Element access
+#//!\name Element access
//! Return by value which contains a pointer (e.g., typedef vertexT * QhullVertex). A reference does not make sense.
T back() const { return last(); }
T first() const { QHULL_ASSERT(!isEmpty()); return *begin(); }
T front() const { return first(); }
T last() const { QHULL_ASSERT(!isEmpty()); return *--end(); }
-#//Modify -- Allocation of opaque types not implemented.
+#//!\name Modify -- Allocation of opaque types not implemented.
-#//Search
+#//!\name Search
bool contains(const T &t) const;
- int count(const T &t) const;
+ countT count(const T &t) const;
-#//Iterator
+#//!\name Iterator
iterator begin() { return begin_node; }
const_iterator begin() const { return begin_node; }
const_iterator constBegin() const { return begin_node; }
const_iterator constEnd() const { return end_node; }
iterator end() { return end_node; }
const_iterator end() const { return end_node; }
class iterator {
private:
T i;
- friend class const_iterator;
+ friend class const_iterator;
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef T value_type;
typedef value_type *pointer;
typedef value_type &reference;
typedef ptrdiff_t difference_type;
iterator() : i() {}
iterator(T t) : i(t) {}
iterator(const iterator &o) : i(o.i) {}
- iterator &operator=(const iterator &o) { i= o.i; return *this; }
+ iterator & operator=(const iterator &o) { i= o.i; return *this; }
T operator*() const { return i; }
T operator->() const { return i; }
bool operator==(const iterator &o) const { return i == o.i; }
bool operator!=(const iterator &o) const { return !operator==(o); }
bool operator==(const const_iterator &o) const { return i==reinterpret_cast(o).i; }
bool operator!=(const const_iterator &o) const { return !operator==(o); }
- iterator &operator++() { i= i.next(); return *this; }
+ iterator & operator++() { i= i.next(); return *this; }
iterator operator++(int) { iterator o= i; i= i.next(); return o; }
- iterator &operator--() { i= i.previous(); return *this; }
+ iterator & operator--() { i= i.previous(); return *this; }
iterator operator--(int) { iterator o= i; i= i.previous(); return o; }
iterator operator+(int j) const;
iterator operator-(int j) const { return operator+(-j); }
- iterator &operator+=(int j) { return *this= *this + j; }
- iterator &operator-=(int j) { return *this= *this - j; }
+ iterator & operator+=(int j) { return *this= *this + j; }
+ iterator & operator-=(int j) { return *this= *this - j; }
};//QhullLinkedList::iterator
class const_iterator {
private:
T i;
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef T value_type;
typedef const value_type *pointer;
typedef const value_type &reference;
typedef ptrdiff_t difference_type;
const_iterator() : i() {}
const_iterator(T t) : i(t) {}
const_iterator(const const_iterator &o) : i(o.i) {}
const_iterator(iterator o) : i(o.i) {}
const_iterator &operator=(const const_iterator &o) { i= o.i; return *this; }
T operator*() const { return i; }
T operator->() const { return i; }
bool operator==(const const_iterator &o) const { return i == o.i; }
bool operator!=(const const_iterator &o) const { return !operator==(o); }
// No comparisons or iterator diff
const_iterator &operator++() { i= i.next(); return *this; }
const_iterator operator++(int) { const_iterator o= i; i= i.next(); return o; }
const_iterator &operator--() { i= i.previous(); return *this; }
const_iterator operator--(int) { const_iterator o= i; i= i.previous(); return o; }
const_iterator operator+(int j) const;
const_iterator operator-(int j) const { return operator+(-j); }
const_iterator &operator+=(int j) { return *this= *this + j; }
const_iterator &operator-=(int j) { return *this= *this - j; }
};//QhullLinkedList::const_iterator
};//QhullLinkedList
template
class QhullLinkedListIterator // FIXUP QH11016 define QhullMutableLinkedListIterator
{
typedef typename QhullLinkedList::const_iterator const_iterator;
const QhullLinkedList *c;
const_iterator i;
public:
QhullLinkedListIterator(const QhullLinkedList &container) : c(&container), i(c->constBegin()) {}
QhullLinkedListIterator &operator=(const QhullLinkedList &container) { c= &container; i= c->constBegin(); return *this; }
bool findNext(const T &t);
bool findPrevious(const T &t);
bool hasNext() const { return i != c->constEnd(); }
bool hasPrevious() const { return i != c->constBegin(); }
T next() { return *i++; }
T peekNext() const { return *i; }
T peekPrevious() const { const_iterator p= i; return *--p; }
T previous() { return *--i; }
void toFront() { i= c->constBegin(); }
void toBack() { i= c->constEnd(); }
};//QhullLinkedListIterator
-#//== Definitions =========================================
+#//!\name == Definitions =========================================
-#//Conversion
+#//!\name Conversion
#ifndef QHULL_NO_STL
template
std::vector QhullLinkedList::
toStdVector() const
{
std::vector tmp;
std::copy(constBegin(), constEnd(), std::back_inserter(tmp));
return tmp;
}//toStdVector
#endif
#ifdef QHULL_USES_QT
template
QList QhullLinkedList::
toQList() const
{
QhullLinkedListIterator i(*this);
QList ls;
while(i.hasNext()){
ls.append(i.next());
}
return ls;
}//toQList
#endif
-#//Read-only
+#//!\name GetSet
template
-int QhullLinkedList::
+countT QhullLinkedList::
count() const
{
const_iterator i= begin_node;
- int c= 0;
+ countT c= 0;
while(i != end_node){
c++;
i++;
}
return c;
}//count
-#//Search
+#//!\name Search
template
bool QhullLinkedList::
contains(const T &t) const
{
const_iterator i= begin_node;
while(i != end_node){
if(i==t){
return true;
}
i++;
}
return false;
}//contains
template
-int QhullLinkedList::
+countT QhullLinkedList::
count(const T &t) const
{
const_iterator i= begin_node;
- int c= 0;
+ countT c= 0;
while(i != end_node){
if(i==t){
c++;
}
i++;
}
return c;
}//count
template
bool QhullLinkedList::
operator==(const QhullLinkedList &l) const
{
if(begin_node==l.begin_node){
return (end_node==l.end_node);
}
T i= begin_node;
T il= l.begin_node;
while(i != end_node){
if(i != il){
return false;
}
i= static_cast(i.next());
il= static_cast(il.next());
}
if(il != l.end_node){
return false;
}
return true;
}//operator==
-#//Iterator
+#//!\name Iterator
template
typename QhullLinkedList::iterator QhullLinkedList::iterator::
operator+(int j) const
{
T n= i;
if(j>0){
while(j--){
n= n.next();
}
}else{
while(j++){
n= n.previous();
}
}
return iterator(n);
}//operator+
template
typename QhullLinkedList::const_iterator QhullLinkedList::const_iterator::
operator+(int j) const
{
T n= i;
if(j>0){
while(j--){
n= n.next();
}
}else{
while(j++){
n= n.previous();
}
}
return const_iterator(n);
}//operator+
-#//QhullLinkedListIterator
+#//!\name QhullLinkedListIterator
template
bool QhullLinkedListIterator::
findNext(const T &t)
{
while(i != c->constEnd()){
if (*i++ == t){
return true;
}
}
return false;
}//findNext
template
bool QhullLinkedListIterator::
findPrevious(const T &t)
{
while(i!=c->constBegin()){
if(*(--i)==t){
return true;
}
}
return false;
}//findNext
}//namespace orgQhull
-#//Global functions
+#//!\name Global
template
std::ostream &
operator<<(std::ostream &os, const orgQhull::QhullLinkedList &qs)
{
typename orgQhull::QhullLinkedList::const_iterator i;
for(i= qs.begin(); i != qs.end(); ++i){
os << *i;
}
return os;
}//operator<<
#endif // QHULLLINKEDLIST_H
diff --git a/src/libqhullcpp/QhullPoint.cpp b/src/libqhullcpp/QhullPoint.cpp
index ca9eda2..2378ad7 100644
--- a/src/libqhullcpp/QhullPoint.cpp
+++ b/src/libqhullcpp/QhullPoint.cpp
@@ -1,177 +1,189 @@
/****************************************************************************
**
** Copyright (c) 2009-2014 C.B. Barber. All rights reserved.
-** $Id: //main/2011/qhull/src/libqhullcpp/QhullPoint.cpp#4 $$Change: 1464 $
-** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+** $Id: //main/2011/qhull/src/libqhullcpp/QhullPoint.cpp#12 $$Change: 1799 $
+** $DateTime: 2014/12/17 16:17:40 $$Author: bbarber $
**
****************************************************************************/
-#include "UsingLibQhull.h"
#include "QhullPoint.h"
+#include "QhullError.h"
+#include "Qhull.h"
#include
#include
#ifdef _MSC_VER // Microsoft Visual C++ -- warning level 4
#endif
namespace orgQhull {
-#//Class public variables and methods
+#//!\name Constructors
-//! If qhRundID undefined uses QhullPoint::s_points_begin and dimension
-int QhullPoint::
-id(int qhRunId, int dimension, const coordT *c)
+
+QhullPoint::
+QhullPoint(const Qhull &q)
+: point_coordinates(0)
+, qh_qh(q.qh())
+, point_dimension(q.hullDimension())
{
- QHULL_UNUSED(dimension);
-
- if(UsingLibQhull::hasPoints()){
- if(qhRunId==UsingLibQhull::NOqhRunId){
- const coordT *pointsEnd;
- int dim;
- const coordT *points= UsingLibQhull::globalPoints(&dim, &pointsEnd);
- if(c>=points && c(c));
- }
- }
- long long i=(long long)c;
- return (int)i; // WARN64
-}//id
+}//QhullPoint
-#//Conversion
+QhullPoint::
+QhullPoint(const Qhull &q, coordT *c)
+: point_coordinates(c)
+, qh_qh(q.qh())
+, point_dimension(q.hullDimension())
+{
+}//QhullPoint dim, coordT
+
+QhullPoint::
+QhullPoint(const Qhull &q, int pointDimension, coordT *c)
+: point_coordinates(c)
+, qh_qh(q.qh())
+, point_dimension(pointDimension)
+{
+}//QhullPoint dim, coordT
+
+QhullPoint::
+QhullPoint(const Qhull &q, Coordinates &c)
+: point_coordinates(c.data())
+, qh_qh(q.qh())
+, point_dimension(c.count())
+{
+}//QhullPoint Coordinates
+
+#//!\name Conversions
// See qt-qhull.cpp for QList conversion
#ifndef QHULL_NO_STL
std::vector QhullPoint::
toStdVector() const
{
QhullPointIterator i(*this);
std::vector