From a61e37f705b2f2174ca88da1204f2646ec51ac0f Mon Sep 17 00:00:00 2001 From: Brad Barber <bradb@shore.net> Date: Mon, 4 Jan 2010 20:45:38 -0500 Subject: [PATCH] Fixed qh_gethash bug and reviewed code Added project files for qhull programs Changed qh_gethash to return an int Changed qh_addhash to take an int --- README.txt | 8 +- cpp/Qhull.h | 6 +- cpp/QhullPoints.cpp | 6 +- cpp/QhullPoints.h | 2 +- qtpro/libqhull/libqhull.pro | 5 +- qtpro/qconvex/qconvex.pro | 27 +++++ qtpro/qdelaunay/qdelaunay.pro | 27 +++++ qtpro/qhalf/qhalf.pro | 27 +++++ qtpro/qhull-all.pro | 10 +- qtpro/qhull/qhull.pro | 3 + qtpro/qvoronoi/qvoronoi.pro | 27 +++++ qtpro/rbox/rbox.pro | 5 +- qtpro/user_eg/user_eg.pro | 25 +++++ qtpro/user_eg2/user_eg2.pro | 25 +++++ qtpro/user_eg3/user_eg3.pro | 2 +- src/Changes.txt | 46 ++++++++- src/io.c | 6 +- src/mem.h | 5 +- src/merge.c | 8 +- src/poly.c | 32 +++--- src/poly.h | 8 +- src/poly2.c | 8 +- src/qconvex.c | 4 +- src/qdelaun.c | 4 +- src/qhalf.c | 4 +- src/qvoronoi.c | 4 +- src/user.h | 2 +- src/user_eg.c | 4 +- src/user_eg2.c | 189 +++++++++++++++++++++++++++++++++- src/userprintf.c | 4 + 30 files changed, 467 insertions(+), 66 deletions(-) create mode 100644 qtpro/qconvex/qconvex.pro create mode 100644 qtpro/qdelaunay/qdelaunay.pro create mode 100644 qtpro/qhalf/qhalf.pro create mode 100644 qtpro/qvoronoi/qvoronoi.pro create mode 100644 qtpro/user_eg/user_eg.pro create mode 100644 qtpro/user_eg2/user_eg2.pro diff --git a/README.txt b/README.txt index 0d2b77c..de59a52 100644 --- a/README.txt +++ b/README.txt @@ -155,7 +155,7 @@ Compiling on Windows 95, 98, NT, 2000, XP Visual C++ quickstart for qhull.exe only: - create a "Win32 console application" called "qhull" - add the following files: - geom.c geom2.c global.c io.c mem.c merge.c poly.c poly2.c qhulllib.c + geom.c geom2.c global.c io.c mem.c merge.c poly.c poly2.c libqhull.c qset.c stat.c unix.c user.c - create a "Win32 console application" called "rbox" - add rbox.c @@ -175,7 +175,7 @@ Compiling on Windows 95, 98, NT, 2000, XP - create a "Win32 static library" called "library" - move these files from "qhull source" - geom.c geom2.c global.c io.c mem.c merge.c poly.c poly2.c qhulllib.c + geom.c geom2.c global.c io.c mem.c merge.c poly.c poly2.c libqhull.c qset.c stat.c user.c - set the library file (use the same for debug and release) - build the project @@ -289,9 +289,9 @@ src/ src/index.htm // index to source files qh-...htm // specific files user.h // header file of user definable constants - qhulllib.h // header file for qhull + libqhull.h // header file for qhull unix.c // Unix front end to qhull - qhulllib.c // Quickhull algorithm with partitioning + libqhull.c // Quickhull algorithm with partitioning user.c // user re-definable functions user_eg.c // example of incorporating qhull into a user program user_eg2.c // more complex example diff --git a/cpp/Qhull.h b/cpp/Qhull.h index 41f426c..4a840b5 100644 --- a/cpp/Qhull.h +++ b/cpp/Qhull.h @@ -1,8 +1,8 @@ /**************************************************************************** ** ** Copyright (C) 2008-2010 C.B. Barber. All rights reserved. -** $Id: //product/qhull/main/rel/cpp/Qhull.h#35 $$Change: 1139 $ -** $DateTime: 2010/01/03 11:20:29 $$Author: bbarber $ +** $Id: //product/qhull/main/rel/cpp/Qhull.h#36 $$Change: 1143 $ +** $DateTime: 2010/01/03 22:41:47 $$Author: bbarber $ ** ****************************************************************************/ @@ -42,7 +42,7 @@ 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_POINTER) + 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) diff --git a/cpp/QhullPoints.cpp b/cpp/QhullPoints.cpp index 95dca9f..e9f1480 100644 --- a/cpp/QhullPoints.cpp +++ b/cpp/QhullPoints.cpp @@ -108,8 +108,8 @@ indexOf(const coordT *coordinates) const return -1; } size_t offset= coordinates-point_first; - int index= (int)offset/dimension(); // int for error reporting - int extra= (int)offset%dimension(); + int index= (int)(offset/(size_t)dimension()); // int for error reporting + int extra= (int)(offset%(size_t)dimension()); if(extra!=0){ throw QhullError(10066, "Qhull error: coordinates %x are not at point boundary (extra %d at index %d)", extra, index, 0.0, coordinates); } @@ -124,7 +124,7 @@ indexOf(const coordT *coordinates, int noThrow) const if(!includesCoordinates(coordinates)||dimension()==0){ return -1; } - extra= (coordinates-point_first)%dimension(); + extra= (coordinates-point_first)%(size_t)dimension(); } return indexOf(coordinates-extra); }//indexOf coordT noThrow diff --git a/cpp/QhullPoints.h b/cpp/QhullPoints.h index 1e86cad..50df2f9 100644 --- a/cpp/QhullPoints.h +++ b/cpp/QhullPoints.h @@ -76,7 +76,7 @@ public: int dimension() const { return point_dimension; } bool empty() const { return point_end==point_first; } coordT *extraCoordinates() const { return extraCoordinatesCount() ? (point_end-extraCoordinatesCount()) : 0; } - int extraCoordinatesCount() const { return point_dimension>0 ? (int)(point_end-point_first)%point_dimension : 0; } // WARN64 + int extraCoordinatesCount() const { return point_dimension>0 ? (int)((point_end-point_first)%(size_t)point_dimension) : 0; } // WARN64 bool includesCoordinates(const coordT *coordinates) const { return coordinates>=point_first && coordinates<point_end; } bool isEmpty() const { return empty(); } bool operator==(const QhullPoints &other) const; diff --git a/qtpro/libqhull/libqhull.pro b/qtpro/libqhull/libqhull.pro index 079f2c0..13a56e5 100644 --- a/qtpro/libqhull/libqhull.pro +++ b/qtpro/libqhull/libqhull.pro @@ -6,8 +6,9 @@ DESTDIR = ../.. TEMPLATE = lib CONFIG += staticlib warn_on CONFIG -= app_bundle qt -QMAKE_CFLAGS_DEBUG += -Wall -Wextra -Wshadow -Wcast-qual -Wwrite-strings -QMAKE_CFLAGS_DEBUG += -Wno-sign-conversion # Many size_t vs. int errors +QMAKE_CFLAGS += -fno-strict-aliasing +QMAKE_CFLAGS += -Wall -Wextra -Wshadow -Wcast-qual -Wwrite-strings +QMAKE_CFLAGS += -Wno-sign-conversion # Many size_t vs. int errors #QMAKE_CFLAGS_DEBUG += -Wconversion # no workaround for bit-field conversion errors build_pass:CONFIG(debug, debug|release):{ TARGET = qhulld diff --git a/qtpro/qconvex/qconvex.pro b/qtpro/qconvex/qconvex.pro new file mode 100644 index 0000000..15515e3 --- /dev/null +++ b/qtpro/qconvex/qconvex.pro @@ -0,0 +1,27 @@ +# ------------------------------------------------- +# qconvex.pro -- Qt project file for qconvex.exe +# ------------------------------------------------- + +TARGET = qconvex +DESTDIR = ../.. +TEMPLATE = app +CONFIG += console warn_on +CONFIG -= app_bundle +LIBS += -L../.. +QMAKE_CFLAGS += -fno-strict-aliasing +QMAKE_CFLAGS += -Wall -Wextra -Wshadow -Wcast-qual -Wwrite-strings +QMAKE_CFLAGS += -Wno-sign-conversion # Many size_t vs. int errors +build_pass:CONFIG(debug, debug|release):{ + LIBS += libqhulld + OBJECTS_DIR = ../../tmp/qconvex/Debug +}else:build_pass:CONFIG(release, debug|release):{ + LIBS += libqhull + OBJECTS_DIR = ../../tmp/qconvex/Release +} +QT -= gui +MOC_DIR = ../../tmp/moc +RCC_DIR = ../../tmp/rcc +INCLUDEPATH = ../../tmp +VPATH = ../.. +SOURCES += src/qconvex.c +HEADERS += src/libqhull.h diff --git a/qtpro/qdelaunay/qdelaunay.pro b/qtpro/qdelaunay/qdelaunay.pro new file mode 100644 index 0000000..e24703c --- /dev/null +++ b/qtpro/qdelaunay/qdelaunay.pro @@ -0,0 +1,27 @@ +# ------------------------------------------------- +# qdelaunay.pro -- Qt project file for qvoronoi.exe +# ------------------------------------------------- + +TARGET = qdelaunay +DESTDIR = ../.. +TEMPLATE = app +CONFIG += console warn_on +CONFIG -= app_bundle +LIBS += -L../.. +QMAKE_CFLAGS += -fno-strict-aliasing +QMAKE_CFLAGS += -Wall -Wextra -Wshadow -Wcast-qual -Wwrite-strings +QMAKE_CFLAGS += -Wno-sign-conversion # Many size_t vs. int errors +build_pass:CONFIG(debug, debug|release):{ + LIBS += libqhulld + OBJECTS_DIR = ../../tmp/qdelaunay/Debug +}else:build_pass:CONFIG(release, debug|release):{ + LIBS += libqhull + OBJECTS_DIR = ../../tmp/qdelaunay/Release +} +QT -= gui +MOC_DIR = ../../tmp/moc +RCC_DIR = ../../tmp/rcc +INCLUDEPATH = ../../tmp +VPATH = ../.. +SOURCES += src/qdelaun.c +HEADERS += src/libqhull.h diff --git a/qtpro/qhalf/qhalf.pro b/qtpro/qhalf/qhalf.pro new file mode 100644 index 0000000..a6a522d --- /dev/null +++ b/qtpro/qhalf/qhalf.pro @@ -0,0 +1,27 @@ +# ------------------------------------------------- +# qhalf.pro -- Qt project file for qconvex.exe +# ------------------------------------------------- + +TARGET = qhalf +DESTDIR = ../.. +TEMPLATE = app +CONFIG += console warn_on +CONFIG -= app_bundle +LIBS += -L../.. +# QMAKE_CFLAGS += -fno-strict-aliasing +QMAKE_CFLAGS += -Wall -Wextra -Wshadow -Wcast-qual -Wwrite-strings +QMAKE_CFLAGS += -Wno-sign-conversion # Many size_t vs. int errors +build_pass:CONFIG(debug, debug|release):{ + LIBS += libqhulld + OBJECTS_DIR = ../../tmp/qconvex/Debug +}else:build_pass:CONFIG(release, debug|release):{ + LIBS += libqhull + OBJECTS_DIR = ../../tmp/qconvex/Release +} +QT -= gui +MOC_DIR = ../../tmp/moc +RCC_DIR = ../../tmp/rcc +INCLUDEPATH = ../../tmp +VPATH = ../.. +SOURCES += src/qhalf.c +HEADERS += src/libqhull.h diff --git a/qtpro/qhull-all.pro b/qtpro/qhull-all.pro index ff58d66..b4ba739 100644 --- a/qtpro/qhull-all.pro +++ b/qtpro/qhull-all.pro @@ -6,8 +6,14 @@ TEMPLATE = subdirs CONFIG += ordered SUBDIRS += libqhull -SUBDIRS += libqhullcpp +SUBDIRS += user_eg +SUBDIRS += user_eg2 SUBDIRS += qhull -SUBDIRS += qhulltest +SUBDIRS += qconvex +SUBDIRS += qdelaunay +SUBDIRS += qhalf +SUBDIRS += qvoronoi SUBDIRS += rbox +SUBDIRS += libqhullcpp SUBDIRS += user_eg3 +SUBDIRS += qhulltest diff --git a/qtpro/qhull/qhull.pro b/qtpro/qhull/qhull.pro index cb63646..910bd52 100644 --- a/qtpro/qhull/qhull.pro +++ b/qtpro/qhull/qhull.pro @@ -8,6 +8,9 @@ TEMPLATE = app CONFIG += console warn_on CONFIG -= app_bundle LIBS += -L../.. +QMAKE_CFLAGS += -fno-strict-aliasing +QMAKE_CFLAGS += -Wall -Wextra -Wshadow -Wcast-qual -Wwrite-strings +QMAKE_CFLAGS += -Wno-sign-conversion # Many size_t vs. int errors build_pass:CONFIG(debug, debug|release):{ LIBS += libqhulld OBJECTS_DIR = ../../tmp/qhull/Debug diff --git a/qtpro/qvoronoi/qvoronoi.pro b/qtpro/qvoronoi/qvoronoi.pro new file mode 100644 index 0000000..53898d8 --- /dev/null +++ b/qtpro/qvoronoi/qvoronoi.pro @@ -0,0 +1,27 @@ +# ------------------------------------------------- +# qvoronoi.pro -- Qt project file for qvoronoi.exe +# ------------------------------------------------- + +TARGET = qvoronoi +DESTDIR = ../.. +TEMPLATE = app +CONFIG += console warn_on +CONFIG -= app_bundle +LIBS += -L../.. +QMAKE_CFLAGS += -fno-strict-aliasing +QMAKE_CFLAGS += -Wall -Wextra -Wshadow -Wcast-qual -Wwrite-strings +QMAKE_CFLAGS += -Wno-sign-conversion # Many size_t vs. int errors +build_pass:CONFIG(debug, debug|release):{ + LIBS += libqhulld + OBJECTS_DIR = ../../tmp/qvoronoi/Debug +}else:build_pass:CONFIG(release, debug|release):{ + LIBS += libqhull + OBJECTS_DIR = ../../tmp/qvoronoi/Release +} +QT -= gui +MOC_DIR = ../../tmp/moc +RCC_DIR = ../../tmp/rcc +INCLUDEPATH = ../../tmp +VPATH = ../.. +SOURCES += src/qvoronoi.c +HEADERS += src/libqhull.h diff --git a/qtpro/rbox/rbox.pro b/qtpro/rbox/rbox.pro index 72afc82..846f506 100644 --- a/qtpro/rbox/rbox.pro +++ b/qtpro/rbox/rbox.pro @@ -4,8 +4,11 @@ TARGET = rbox DESTDIR = ../.. TEMPLATE = app -CONFIG += console +CONFIG += console warn_on LIBS += -L../.. +QMAKE_CFLAGS += -fno-strict-aliasing +QMAKE_CFLAGS += -Wall -Wextra -Wshadow -Wcast-qual -Wwrite-strings +QMAKE_CFLAGS += -Wno-sign-conversion # Many size_t vs. int errors build_pass:CONFIG(debug, debug|release):{ LIBS += libqhulld OBJECTS_DIR = ../../tmp/rbox/Debug diff --git a/qtpro/user_eg/user_eg.pro b/qtpro/user_eg/user_eg.pro new file mode 100644 index 0000000..5e99dd4 --- /dev/null +++ b/qtpro/user_eg/user_eg.pro @@ -0,0 +1,25 @@ +# ------------------------------------------------- +# user_eg.pro -- Qt project for Qhull demonstration +# ------------------------------------------------- +TARGET = user_eg +DESTDIR = ../.. +TEMPLATE = app +CONFIG += console warn_on +CONFIG -= app_bundle +LIBS += -L../.. +QMAKE_CFLAGS += -fno-strict-aliasing +QMAKE_CFLAGS += -Wall -Wextra -Wshadow -Wcast-qual -Wwrite-strings +QMAKE_CFLAGS += -Wno-sign-conversion # Many size_t vs. int errors +build_pass:CONFIG(debug, debug|release):{ + LIBS += libqhulld + OBJECTS_DIR = ../../tmp/user_eg/Debug +}else:build_pass:CONFIG(release, debug|release):{ + LIBS += libqhull + OBJECTS_DIR = ../../tmp/user_eg/Release +} +QT -= gui +CONFIG -= app_bundle +INCLUDEPATH = ../../tmp +VPATH = ../.. +SOURCES += src/user_eg.c +HEADERS += src/qhull_a.h diff --git a/qtpro/user_eg2/user_eg2.pro b/qtpro/user_eg2/user_eg2.pro new file mode 100644 index 0000000..acda9fb --- /dev/null +++ b/qtpro/user_eg2/user_eg2.pro @@ -0,0 +1,25 @@ +# ------------------------------------------------- +# user_eg2.pro -- Qt project for Qhull demonstration +# ------------------------------------------------- +TARGET = user_eg2 +DESTDIR = ../.. +TEMPLATE = app +CONFIG += console warn_on +CONFIG -= app_bundle +LIBS += -L../.. +QMAKE_CFLAGS += -fno-strict-aliasing +QMAKE_CFLAGS += -Wall -Wextra -Wshadow -Wcast-qual -Wwrite-strings +QMAKE_CFLAGS += -Wno-sign-conversion # Many size_t vs. int errors +build_pass:CONFIG(debug, debug|release):{ + LIBS += libqhulld + OBJECTS_DIR = ../../tmp/user_eg2/Debug +}else:build_pass:CONFIG(release, debug|release):{ + LIBS += libqhull + OBJECTS_DIR = ../../tmp/user_eg2/Release +} +QT -= gui +CONFIG -= app_bundle +INCLUDEPATH = ../../tmp +VPATH = ../.. +SOURCES += src/user_eg2.c +HEADERS += src/libqhull.h diff --git a/qtpro/user_eg3/user_eg3.pro b/qtpro/user_eg3/user_eg3.pro index 5b987d7..4cd127f 100644 --- a/qtpro/user_eg3/user_eg3.pro +++ b/qtpro/user_eg3/user_eg3.pro @@ -4,7 +4,7 @@ TARGET = user_eg3 DESTDIR = ../.. TEMPLATE = app -CONFIG += console +CONFIG += console warn_on LIBS += -L../.. build_pass:CONFIG(debug, debug|release):{ LIBS += libqhullcppd diff --git a/src/Changes.txt b/src/Changes.txt index af1e6ff..60b06fc 100644 --- a/src/Changes.txt +++ b/src/Changes.txt @@ -4,7 +4,7 @@ To do for 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 +- 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 @@ -27,6 +27,7 @@ To do for documentation - Check globalAngleEpsilon - Deprecate save_qhull() - Review email for doc changes + - Add option Ta to qhull.man, etc. To do for suggestions C++ class for access to statistics, accumulate vs. add @@ -82,13 +83,47 @@ To do Keep size of qh_set as int, set.h, global.c Keep size of qh_mem as int, mem.h, global.c Why rename index in qh_initthresholds(), poly2.c, qhull.c -- Seems OK - - Run qhull regression tests - Measure performance of Qhull - - qhulltest --all + - qhulltest --all added to output - Number the FIXUPS - - Review diffs against qhull 2003.1 - Review qh-code.htm#cpp - Add test of user_eg3, etc. + - Add vcproj for qconvex, etc. + - Review all ptr_intT + + - Run qhull regression tests + + Output warning Qc + rbox d D2 | qhull FQ n | qhalf s H0 Fc FP Fn FN FQ Fv Fx + + Failed. Premature exit + rbox 1000 W0 | qhull QR2 QJ s Fs Tv + + t not printed + Statistics for: rbox 1000 W1e-20 t | qhull Tcv Qc + + 6668,7x outer plane + Statistics for: rbox 1000 L100000 s G1e-6 t | qhull Tv Q10 + + 5135.7x outer plane + Statistics for: rbox 1000 s W1e-13 t | qhull d Tv + + +qhull 2010.0.2 + +Fixed bugs +- qh_gethash [poly.c]: fix sign conversion. Previously, the result may be negative, leading to a segfault. + The bug is more likely with large address spaces + Reviewed all uses of %(modulo) for remainder with negative arguments + +Breaking code changes +- Return type of qh_gethash changed from unsigned to int. Matches 'size' +- addhash takes a signed hash + qh_addhash( newelem, hashtable, hashsize, hash ) +- Check for wraparound of 64-bit ints -- e.g., a large set + +Code changes +- Test for qh_qh in qh_printf qhull 2010.0.1 2010/01/03 @@ -104,6 +139,7 @@ Preliminary C++ support: Changes to qhull options and results - Allow 'd' and 'v' as the filename for 'TO ..' and 'TI ...' in qdelaunay [M. Jambon] - Allow quoted filenames for 'TO ...' and 'TI ...' + - Preceed error messages and warnings with a message code (e.g., QH6012) - Fixed rbox ignoring flags that were not separated by spaces - Report all hidden options before exiting in qh_checkflags() - Defined qh_OPTIONline [user.h] as max length of option line ('FO') @@ -118,7 +154,6 @@ Breaking Code Changes: - qh_restore_qhull() zeroes out qh.old_qhstat and qh.old_tempstack. Ownership moved. - Rewrote save_qhull/restore_qhull - Add Ztotcheck to zzdef_ [R. Gardener] - - Add message code to error messages and warnings (e.g., QH6012) - Changed qh_malloc to size_t (was unsigned long) - Declare qh_PRINT instead of int [kwilliams] - In qh_printafacet(), changed error output to 'qh ferr' @@ -216,6 +251,7 @@ Documentation: - 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 diff --git a/src/io.c b/src/io.c index 91b522c..3cafbf7 100644 --- a/src/io.c +++ b/src/io.c @@ -14,8 +14,8 @@ This allows the user to avoid loading io.o from qhull.a copyright (c) 1993-2010 The Geometry Center. - $Id: //product/qhull/main/rel/src/io.c#33 $$Change: 1137 $ - $DateTime: 2010/01/02 21:58:11 $$Author: bbarber $ + $Id: //product/qhull/main/rel/src/io.c#34 $$Change: 1144 $ + $DateTime: 2010/01/04 18:23:37 $$Author: bbarber $ */ #include "qhull_a.h" @@ -1382,7 +1382,7 @@ void qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, b qh_fprintf(fp, 9042, "1 "); } qh_fprintf(fp, 9043, "# 1 point per line\n1 "); - for (i=num-1; i--; ) { + for (i=num-1; i--; ) { /* num at least 3 for D2 */ if (i % 20 == 0) qh_fprintf(fp, 9044, "\n"); qh_fprintf(fp, 9045, "0 "); diff --git a/src/mem.h b/src/mem.h index 4690034..0d2f8f3 100644 --- a/src/mem.h +++ b/src/mem.h @@ -12,8 +12,8 @@ qh_errexit(qhmem_ERRqhull, NULL, NULL) otherwise copyright (c) 1993-2010 The Geometry Center. - $Id: //product/qhull/main/rel/src/mem.h#25 $$Change: 1137 $ - $DateTime: 2010/01/02 21:58:11 $$Author: bbarber $ + $Id: //product/qhull/main/rel/src/mem.h#26 $$Change: 1144 $ + $DateTime: 2010/01/04 18:23:37 $$Author: bbarber $ */ #ifndef qhDEFmem @@ -74,6 +74,7 @@ Trace short and quick memory allocations at T5 On 64-bit machines, a pointer may be larger than an 'int'. qh_meminit()/mem.c checks that 'ptr_intT' holds a 'void*' ptr_intT is not defined as 'long long' for portability to older compilers + ptr_intT is signed size_t is typically unsigned, but should match the parameter type Qhull uses int instead of size_t except for system calls such as malloc, qsort, qh_malloc, etc. */ diff --git a/src/merge.c b/src/merge.c index 91c36b1..172e959 100644 --- a/src/merge.c +++ b/src/merge.c @@ -21,8 +21,8 @@ vertex->neighbors not set until the first merge occurs copyright (c) 1993-2010 C.B. Barber. - $Id: //product/qhull/main/rel/src/merge.c#25 $$Change: 1139 $ - $DateTime: 2010/01/03 11:20:29 $$Author: bbarber $ + $Id: //product/qhull/main/rel/src/merge.c#26 $$Change: 1144 $ + $DateTime: 2010/01/04 18:23:37 $$Author: bbarber $ */ #include "qhull_a.h" @@ -1272,7 +1272,7 @@ void qh_hashridge(setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvert int hash; ridgeT *ridgeA; - hash= (int)qh_gethash(hashsize, ridge->vertices, qh hull_dim-1, 0, oldvertex); + hash= qh_gethash(hashsize, ridge->vertices, qh hull_dim-1, 0, oldvertex); while (True) { if (!(ridgeA= SETelemt_(hashtable, hash, ridgeT))) { SETelem_(hashtable, hash)= ridge; @@ -1318,7 +1318,7 @@ ridgeT *qh_hashridge_find(setT *hashtable, int hashsize, ridgeT *ridge, *hashslot= 0; zinc_(Zhashridge); - hash= (int)qh_gethash(hashsize, ridge->vertices, qh hull_dim-1, 0, vertex); + hash= qh_gethash(hashsize, ridge->vertices, qh hull_dim-1, 0, vertex); while ((ridgeA= SETelemt_(hashtable, hash, ridgeT))) { if (ridgeA == ridge) *hashslot= -1; diff --git a/src/poly.c b/src/poly.c index 8326ab9..41e2466 100644 --- a/src/poly.c +++ b/src/poly.c @@ -10,8 +10,8 @@ (all but top 50 and their callers 12/3/95) copyright (c) 1993-2010 The Geometry Center. - $Id: //product/qhull/main/rel/src/poly.c#23 $$Change: 1137 $ - $DateTime: 2010/01/02 21:58:11 $$Author: bbarber $ + $Id: //product/qhull/main/rel/src/poly.c#24 $$Change: 1144 $ + $DateTime: 2010/01/04 18:23:37 $$Author: bbarber $ */ #include "qhull_a.h" @@ -395,18 +395,20 @@ setT *qh_facetintersect(facetT *facetA, facetT *facetB, return hashvalue for a set with firstindex and skipelem notes: + returned hash is in [0,hashsize) assumes at least firstindex+1 elements assumes skipelem is NULL, in set, or part of hash hashes memory addresses which may change over different runs of the same data using sum for hash does badly in high d */ -unsigned qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem) { +int qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem) { void **elemp= SETelemaddr_(set, firstindex, void); ptr_intT hash = 0, elem; + unsigned result; int i; #ifdef _MSC_VER /* Microsoft Visual C++ -- warn about 64-bit issues */ -#pragma warning( push) /* WARN64 -- ptr_intT was defined for 64-bit issues */ +#pragma warning( push) /* WARN64 -- ptr_intT holds a 64-bit pointer */ #pragma warning( disable : 4311) /* 'type cast': pointer truncation from 'void*' to 'ptr_intT' */ #endif @@ -447,9 +449,14 @@ unsigned qh_gethash(int hashsize, setT *set, int size, int firstindex, void *ski }while (*elemp); break; } - hash %= (ptr_intT) hashsize; - /* hash= 0; for debugging purposes */ - return hash; + if (hashsize<0) { + qh_fprintf(qh ferr, 6232, "qhull internal error: negative hashsize %d passed to qh_gethash [poly.c]\n", hashsize); + qh_errexit2 (qh_ERRqhull, NULL, NULL); + } + result= (unsigned)hash; + result %= (unsigned)hashsize; + /* result= 0; for debugging */ + return result; #ifdef _MSC_VER #pragma warning( pop) #endif @@ -717,17 +724,16 @@ facetT *qh_makenew_simplicial(facetT *visible, vertexT *apex, int *numnew) { void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize, int *hashcount) { boolT newfound= False; /* True, if new facet is already in hash chain */ boolT same, ismatch; - unsigned hash; - int scan; + int hash, scan; facetT *facet, *matchfacet; int skip, matchskip; hash= qh_gethash(hashsize, newfacet->vertices, qh hull_dim, 1, SETelem_(newfacet->vertices, newskip)); - trace4((qh ferr, 4050, "qh_matchneighbor: newfacet f%d skip %d hash %ud hashcount %d\n", + trace4((qh ferr, 4050, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n", newfacet->id, newskip, hash, *hashcount)); zinc_(Zhashlookup); - for (scan= (int)hash; (facet= SETelemt_(qh hash_table, scan, facetT)); + for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT)); scan= (++scan >= hashsize ? 0 : scan)) { if (facet == newfacet) { newfound= True; @@ -781,7 +787,7 @@ void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize, int *hashcoun *hashcount += 2; } } - trace4((qh ferr, 4052, "qh_matchneighbor: new f%d skip %d duplicates ridge for f%d skip %d matching f%d ismatch %d at hash %ud\n", + trace4((qh ferr, 4052, "qh_matchneighbor: new f%d skip %d duplicates ridge for f%d skip %d matching f%d ismatch %d at hash %d\n", newfacet->id, newskip, facet->id, skip, (matchfacet == qh_DUPLICATEridge ? -2 : getid_(matchfacet)), ismatch, hash)); @@ -791,7 +797,7 @@ void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize, int *hashcoun if (!newfound) SETelem_(qh hash_table, scan)= newfacet; /* same as qh_addhash */ (*hashcount)++; - trace4((qh ferr, 4053, "qh_matchneighbor: no match for f%d skip %d at hash %ud\n", + trace4((qh ferr, 4053, "qh_matchneighbor: no match for f%d skip %d at hash %d\n", newfacet->id, newskip, hash)); } /* matchneighbor */ diff --git a/src/poly.h b/src/poly.h index 7413f19..06854e9 100644 --- a/src/poly.h +++ b/src/poly.h @@ -7,8 +7,8 @@ see qh-poly.htm, libqhull.h and poly.c copyright (c) 1993-2010 The Geometry Center. - $Id: //product/qhull/main/rel/src/poly.h#20 $$Change: 1137 $ - $DateTime: 2010/01/02 21:58:11 $$Author: bbarber $ + $Id: //product/qhull/main/rel/src/poly.h#21 $$Change: 1144 $ + $DateTime: 2010/01/04 18:23:37 $$Author: bbarber $ */ #ifndef qhDEFpoly @@ -214,7 +214,7 @@ boolT qh_checkflipped(facetT *facet, realT *dist, boolT allerror); void qh_delfacet(facetT *facet); void qh_deletevisible(void /*qh visible_list, qh horizon_list*/); setT *qh_facetintersect(facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra); -unsigned qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem); +int qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem); facetT *qh_makenewfacet(setT *vertices, boolT toporient, facetT *facet); void qh_makenewplanes(void /* newfacet_list */); facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew); @@ -234,7 +234,7 @@ void qh_updatevertices(void); /*========== -prototypes poly2.c in alphabetical order ===========*/ -void qh_addhash(void* newelem, setT *hashtable, int hashsize, unsigned hash); +void qh_addhash(void* newelem, setT *hashtable, int hashsize, int hash); void qh_check_bestdist(void); void qh_check_maxout(void); void qh_check_output(void); diff --git a/src/poly2.c b/src/poly2.c index 1626f58..eb37615 100644 --- a/src/poly2.c +++ b/src/poly2.c @@ -9,8 +9,8 @@ frequently used code is in poly.c copyright (c) 1993-2010 The Geometry Center. - $Id: //product/qhull/main/rel/src/poly2.c#35 $$Change: 1137 $ - $DateTime: 2010/01/02 21:58:11 $$Author: bbarber $ + $Id: //product/qhull/main/rel/src/poly2.c#36 $$Change: 1144 $ + $DateTime: 2010/01/04 18:23:37 $$Author: bbarber $ */ #include "qhull_a.h" @@ -23,7 +23,7 @@ qh_addhash( newelem, hashtable, hashsize, hash ) add newelem to linear hash table at hash if not already there */ -void qh_addhash(void* newelem, setT *hashtable, int hashsize, unsigned hash) { +void qh_addhash(void* newelem, setT *hashtable, int hashsize, int hash) { int scan; void *elem; @@ -2034,7 +2034,7 @@ void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcoun int skip, newskip, nextskip= 0, maxskip= 0, maxskip2= 0, makematch; realT maxdist= -REALmax, mindist, dist2, low, high; - hash= (int)qh_gethash(hashsize, atfacet->vertices, qh hull_dim, 1, + hash= qh_gethash(hashsize, atfacet->vertices, qh hull_dim, 1, SETelem_(atfacet->vertices, atskip)); trace2((qh ferr, 2046, "qh_matchduplicates: find duplicate matches for f%d skip %d hash %d hashcount %d\n", atfacet->id, atskip, hash, *hashcount)); diff --git a/src/qconvex.c b/src/qconvex.c index ab5b0d8..326b0bb 100644 --- a/src/qconvex.c +++ b/src/qconvex.c @@ -14,7 +14,7 @@ #include <string.h> #include <ctype.h> #include <math.h> -#include "qhulllib.h" +#include "libqhull.h" #include "mem.h" #include "qset.h" @@ -45,7 +45,7 @@ int isatty(int); /* returns 1 if stdin is a tty long prompt for qconvex notes: - restricted version of qhulllib.c + restricted version of libqhull.c see: concise prompt below diff --git a/src/qdelaun.c b/src/qdelaun.c index ede62cd..61c361e 100644 --- a/src/qdelaun.c +++ b/src/qdelaun.c @@ -15,7 +15,7 @@ #include <string.h> #include <ctype.h> #include <math.h> -#include "qhulllib.h" +#include "libqhull.h" #include "mem.h" #include "qset.h" @@ -46,7 +46,7 @@ int isatty(int); /* returns 1 if stdin is a tty long prompt for qhull notes: - restricted version of qhulllib.c + restricted version of libqhull.c see: concise prompt below diff --git a/src/qhalf.c b/src/qhalf.c index dba64e7..fa5f7a7 100644 --- a/src/qhalf.c +++ b/src/qhalf.c @@ -14,7 +14,7 @@ #include <string.h> #include <ctype.h> #include <math.h> -#include "qhulllib.h" +#include "libqhull.h" #include "mem.h" #include "qset.h" @@ -45,7 +45,7 @@ int isatty(int); /* returns 1 if stdin is a tty long prompt for qhull notes: - restricted version of qhulllib.c + restricted version of libqhull.c see: concise prompt below diff --git a/src/qvoronoi.c b/src/qvoronoi.c index 14dd3ca..3893ba3 100644 --- a/src/qvoronoi.c +++ b/src/qvoronoi.c @@ -15,7 +15,7 @@ #include <string.h> #include <ctype.h> #include <math.h> -#include "qhulllib.h" +#include "libqhull.h" #include "mem.h" #include "qset.h" @@ -46,7 +46,7 @@ int isatty(int); /* returns 1 if stdin is a tty long prompt for qhull notes: - restricted version of qhulllib.c + restricted version of libqhull.c see: concise prompt below diff --git a/src/user.h b/src/user.h index 5cbf142..03c16a7 100644 --- a/src/user.h +++ b/src/user.h @@ -47,7 +47,7 @@ Code flags -- If add new messages, assign these values and increment. - def counters = [27, 1047, 2059, 3025, 4068, 5003, 6232, 7078, 8143, 9410] + def counters = [27, 1047, 2059, 3025, 4068, 5003, 6233, 7078, 8143, 9410] See: qh_ERR* [libqhull.h] */ diff --git a/src/user_eg.c b/src/user_eg.c index 080acc8..fb5524d 100644 --- a/src/user_eg.c +++ b/src/user_eg.c @@ -36,13 +36,13 @@ These examples, call qh_qhull() directly. They allow tighter control on the code loaded with Qhull. - For a simple C++ example, see qhull_interface.cpp + For a C++ example, see user_eg3.cpp Summaries are sent to stderr if other output formats are used compiled by 'make user_eg' - see qhulllib.h for data structures, macros, and user-callable functions. + see libqhull.h for data structures, macros, and user-callable functions. */ #include "qhull_a.h" diff --git a/src/user_eg2.c b/src/user_eg2.c index da2c77f..afffbd7 100644 --- a/src/user_eg2.c +++ b/src/user_eg2.c @@ -9,6 +9,8 @@ The method used here and in unix.c gives you additional control over Qhull. + See user_eg3.cpp for a C++ example + call with: user_eg2 "triangulated cube/diamond options" "delaunay options" "halfspace options" @@ -39,7 +41,7 @@ derived from unix.c and compiled by 'make user_eg2' - see qhulllib.h for data structures, macros, and user-callable functions. + see libqhull.h for data structures, macros, and user-callable functions. If you want to control all output to stdio and input to stdin, set the #if below to "1" and delete all lines that contain "io.c". @@ -468,9 +470,11 @@ your project.\n\n"); -errexit- return exitcode to system after an error assumes exitcode non-zero prints useful information - see qh_errexit2() in qhulllib.c for 2 facets + see qh_errexit2() in libqhull.c for 2 facets */ void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) { + QHULL_UNUSED(facet); + QHULL_UNUSED(ridge); if (qh ERREXITcalled) { fprintf (qh ferr, "qhull error while processing previous error. Exit program\n"); @@ -506,7 +510,7 @@ void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) { -errprint- prints out the information of the erroneous object any parameter may be NULL, also prints neighbors and geomview output */ -void qh_errprint(char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) { +void qh_errprint(const char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) { fprintf (qh ferr, "%s facets f%d f%d ridge r%d vertex v%d\n", string, getid_(atfacet), getid_(otherfacet), getid_(atridge), @@ -529,6 +533,185 @@ void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall) { fprintf( qh ferr, "facet f%d\n", facet->id); } /* 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\ +A coplanar point may lead to a wide facet. Options 'QbB' (scale to unit box)\n\ +or 'Qbb' (scale last coordinate) may remove this warning. Use 'Pp' to skip\n\ +this warning. See 'Limitations' in qh-impre.htm.\n", + -minangle); /* convert from angle between normals to angle between facets */ +} /* printhelp_narrowhull */ + +/* qh_printhelp_singular + 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\ +"); + if (qh DELAUNAY && !qh ATinfinity) + qh_fprintf(fp, 9390, "\n\n\ +This is a Delaunay triangulation and the input is co-circular or co-spherical:\n\ + - use 'Qz' to add a point \"at infinity\" (i.e., above the paraboloid)\n\ + - or use 'QJ' to joggle the input and avoid co-circular data\n"); + } +} /* printhelp_singular */ /*----------------------------------------- diff --git a/src/userprintf.c b/src/userprintf.c index 1b4fbc9..0a295c3 100644 --- a/src/userprintf.c +++ b/src/userprintf.c @@ -47,7 +47,11 @@ void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... ) { qh_errexit(6232, NULL, NULL); } va_start(args, fmt); +#if qh_QHpointer + if (qh_qh && qh ANNOTATEoutput) { +#else if (qh ANNOTATEoutput) { +#endif fprintf(fp, "[QH%.4d]", msgcode); }else if (msgcode >= MSG_ERROR && msgcode < MSG_STDERR ) { fprintf(fp, "QH%.4d ", msgcode); -- GitLab