45 #if defined (HAVE_QHULL)
47 # if defined (NEED_QHULL_VERSION)
48 char qh_version[] =
"convhulln.oct 2007-07-24";
65 if (dim > maxval || n > maxval)
67 error (
"%s: dimension too large for Qhull", who);
77 @deftypefn {Loadable Function} {@var{h} =} convhulln (@var{pts})\n\
78 @deftypefnx {Loadable Function} {@var{h} =} convhulln (@var{pts}, @var{options})\n\
79 @deftypefnx {Loadable Function} {[@var{h}, @var{v}] =} convhulln (@dots{})\n\
80 Compute the convex hull of the set of points @var{pts}.\n\
82 @var{pts} is a matrix of size [n, dim] containing n points in a space of\n\
85 The hull @var{h} is an index vector into the set of points and specifies\n\
86 which points form the enclosing hull.\n\
88 An optional second argument, which must be a string or cell array of strings,\n\
89 contains options passed to the underlying qhull command.\n\
90 See the documentation for the Qhull library for details\n\
91 @url{http://www.qhull.org/html/qh-quick.htm#options}.\n\
92 The default options depend on the dimension of the input:\n\
95 @item 2D, 3D, 4D: @var{options} = @code{@{\"Qt\"@}}\n\
97 @item 5D and higher: @var{options} = @code{@{\"Qt\", \"Qx\"@}}\n\
100 If @var{options} is not present or @code{[]} then the default arguments are\n\
101 used. Otherwise, @var{options} replaces the default argument list.\n\
102 To append user options to the defaults it is necessary to repeat the\n\
103 default arguments in @var{options}. Use a null string to pass no arguments.\n\
105 If the second output @var{v} is requested the volume of the enclosing\n\
106 convex hull is calculated.\n\n\
107 @seealso{convhull, delaunayn, voronoin}\n\
112 #if defined (HAVE_QHULL)
114 int nargin = args.
length ();
115 if (nargin < 1 || nargin > 2)
121 Matrix points (args(0).matrix_value ());
139 if (args(1).is_string ())
140 options =
" " + args(1).string_value ();
141 else if (args(1).is_empty ())
143 else if (args(1).is_cellstr ())
150 options +=
" " + tmp(i);
154 error (
"convhulln: OPTIONS must be a string, cell array of strings, or empty");
159 boolT ismalloc =
false;
164 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)
165 FILE *outfile = gnulib::fopen (
"NUL",
"w");
167 FILE *outfile = gnulib::fopen (
"/dev/null",
"w");
169 FILE *errfile = stderr;
175 error (
"convhulln: unable to create temporary file for output");
181 std::string cmd =
"qhull" + options;
185 strcpy (cmd_str, cmd.c_str ());
187 int exitcode = qh_new_qhull (dim, num_points, points.
fortran_vec (),
188 ismalloc, cmd_str, outfile, errfile);
191 bool nonsimp_seen =
false;
205 if (! (nonsimp_seen || facet->simplicial || qh hull_dim == 2))
209 if (cmd.find (
"QJ") != std::string::npos)
212 error (
"convhulln: qhull failed: option 'QJ' returned non-simplicial facet");
219 setT *vertices = qh_facet3vertex (facet);
221 vertexT *vertex, **vertexp;
223 FOREACHvertex_ (vertices)
224 idx(i, j++) = 1 + qh_pointid(vertex->point);
226 qh_settempfree (&vertices);
230 if (facet->toporient ^ qh_ORIENTclock)
232 vertexT *vertex, **vertexp;
234 FOREACHvertex_ (facet->vertices)
235 idx(i, j++) = 1 + qh_pointid(vertex->point);
239 vertexT *vertex, **vertexp;
241 FOREACHvertexreverse12_ (facet->vertices)
242 idx(i, j++) = 1 + qh_pointid(vertex->point);
246 warning (
"convhulln: facet %d only has %d vertices", i, j);
254 idx.
resize (nf, dim, 0.0);
268 if (facet->upperdelaunay && qh ATinfinity)
271 facet->f.area = area = qh_facetarea (facet);
272 facet->isarea = True;
276 if (facet->upperdelaunay == qh UPPERdelaunay)
282 qh_distplane (qh interior_point, facet, &dist);
283 qh totvol += -dist * area/ qh hull_dim;
293 error (
"convhulln: qhull failed");
296 qh_freeqhull (! qh_ALL);
298 int curlong, totlong;
299 qh_memfreeshort (&curlong, &totlong);
301 if (curlong || totlong)
302 warning (
"convhulln: did not free %d bytes of long memory (%d pieces)",
306 error (
"convhulln: not available in this version of Octave");
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
OCTINTERP_API void print_usage(void)
octave_idx_type numel(void) const
Number of elements in the array.
octave_idx_type length(void) const
void error(const char *fmt,...)
static void close_fcn(FILE *f)
octave_idx_type rows(void) const
F77_RET_T const double const double * f
void add_fcn(void(*fcn)(void))
Matrix transpose(void) const
void warning(const char *fmt,...)
charNDArray max(char d, const charNDArray &m)
static bool octave_qhull_dims_ok(octave_idx_type dim, octave_idx_type n, const char *who)
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
#define DEFUN_DLD(name, args_name, nargout_name, doc)
const T * fortran_vec(void) const
octave_idx_type columns(void) const
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))