Mercurial > forge
changeset 2319:e9ec09d4cba4 octave-forge
decompose all non-simplicial facets and change Qhull options
author | abarth93 |
---|---|
date | Tue, 06 Jun 2006 16:32:05 +0000 |
parents | c4d3e8040350 |
children | b4943239bbfe |
files | main/geometry/delaunayn.cc |
diffstat | 1 files changed, 115 insertions(+), 41 deletions(-) [+] |
line wrap: on
line diff
--- a/main/geometry/delaunayn.cc Tue Jun 06 13:42:45 2006 +0000 +++ b/main/geometry/delaunayn.cc Tue Jun 06 16:32:05 2006 +0000 @@ -16,28 +16,37 @@ */ /* -16. July 2000 - Kai Habel: first release + 16. July 2000 - Kai Habel: first release -25. September 2002 - Changes by Rafael Laboissiere <rafael@laboissiere.net> + 25. September 2002 - Changes by Rafael Laboissiere <rafael@laboissiere.net> - * Added Qbb option to normalize the input and avoid crashes in Octave. - * delaunayn accepts now a second (optional) argument that must be a string - containing extra options to the qhull command. - * Fixed doc string. The dimension of the result matrix is [m, dim+1], and - not [n, dim-1]. + * Added Qbb option to normalize the input and avoid crashes in Octave. + * delaunayn accepts now a second (optional) argument that must be a string + containing extra options to the qhull command. + * Fixed doc string. The dimension of the result matrix is [m, dim+1], and + not [n, dim-1]. + + 6. June 2006: Changes by Alexander Barth <abarth@marine.usf.edu> + + * triangulate non-simplicial facets + * allow options to be specified as cell array of strings + * change the default options (for compatibility with matlab) */ #include "config.h" extern "C" { - #include "qhull/qhull_a.h" +#include "qhull/qhull_a.h" } #include <iostream> +#include <string> + #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <octave/oct.h> +#include "ov-cell.h" #ifdef NEED_QHULL_VERSION char qh_version[] = "delaunayn.oct 2003-12-14"; @@ -45,27 +54,37 @@ FILE *outfile = stdout; FILE *errfile = stderr; char flags[250]; -const char *options; DEFUN_DLD (delaunayn, args, , - "-*- texinfo -*-\n\ + "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {@var{T}=} delaunayn (@var{P}[, @var{opt}])\n\ Form the Delaunay triangulation for a set of points.\n\ -The Delaunay trianugulation is a tessellation of the convex hull of the\n\ +The Delaunay triangulation is a tessellation of the convex hull of the\n\ points such that no n-sphere defined by the n-triangles contains\n\ any other points from the set.\n\n\ -The input matrix of size [n, dim] contains n points of dimension dim.\n\ +The input matrix @var{P} of size [n, dim] contains n points in a space of dimension dim.\n\ The return matrix @var{T} has the size [m, dim+1]. It contains for\n\ each row a set of indices to the points, which describes a simplex of\n\ -dimension dim. The 3d simplex is a tetrahedron.\n\n\ -If a second optional argument is given, it must be a string containing\n\ -extra options for the underlying qhull command. In particular, \"Qt\"\n\ -may be useful for joggling the input to cope with non-simplicial cases.\n\ -(See the Qhull documentation for the available options.) @end deftypefn") +dimension dim. For example, a 2d simplex is a triangle and 3d simplex is a tetrahedron.\n\n\ +Extra options for the underlying Qhull command can be specified by the second \ +argument. This argument is a cell array of strings. The default options depend on the dimension \ +of the input: \n\ +@itemize \n\ +@item 2D and 3D: @var{opt} = @{'Qt','Qbb','Qc'@} \ +@item 4D and higher: @var{opt} = @{'Qt','Qbb','Qc','Qz'@} \ +@end itemize \n\n\ +If @var{opt} is [], then the default arguments are used. \ +If @var{opt} is @{'@w{}'@}, then none of the default arguments are used by Qhull. \n\ +See the Qhull documentation for the available options. \n\n\ +All options can also be specified as single string, for example 'Qt Qbb Qc Qz'. \n\n\ +NOTE: The default options of delaunayn have changed. Use \n\ +@var{OPT}= @{'Qbb','T0'@} to reproduce the output of previous version. \ +@end deftypefn") { octave_value_list retval; retval(0) = 0.0; + std::string options = ""; int nargin = args.length(); if (nargin < 1 || nargin > 2) { @@ -73,20 +92,46 @@ return retval; } + Matrix p(args(0).matrix_value()); + const int dim = p.columns(); + const int n = p.rows(); + + // default options + if (dim <= 3) + options = "Qt Qbb Qc"; + else + options = "Qt Qbb Qc Qx"; + + if (nargin == 2) { - if ( ! args (1).is_string () ) { - error ("delaunayn: second argument must be a string"); + if (args(1).is_empty() ) { + // keep default options + } + else if ( args(1).is_string () ) { + // option string is directly provided + options = args(1).string_value(); + } + else if ( args(1).is_cell () ) { + options = ""; + + Cell c = args(1).cell_value(); + for (int i=0; i < c.numel(); i++) { + + if (!c.elem(i).is_string()) { + error ("delaunayn: all options must be strings"); + return retval; + } + + options = options + c.elem(i).string_value() + " "; + } + } + else { + error ("delaunayn: second argument must be a string, cell of stringsor empty"); return retval; } - options = args (1).string_value().c_str(); - } - else - options = ""; + } - Matrix p(args(0).matrix_value()); - - const int dim = p.columns(); - const int n = p.rows(); + //octave_stdout << "options " << options << std::endl; if (n > dim) { @@ -94,26 +139,53 @@ double *pt_array = p.fortran_vec(); boolT ismalloc = False; - sprintf(flags,"qhull d Qbb T0 %s",options); - if (!qh_new_qhull (dim, n, pt_array, ismalloc, flags, NULL, errfile)) { + sprintf(flags,"qhull d %s",options.c_str()); + + /*If you want some debugging information replace the NULL + pointer with outfile. + */ - /*If you want some debugging information replace the NULL - pointer with outfile. - */ + int exitcode = qh_new_qhull (dim, n, pt_array, ismalloc,flags, NULL, errfile); + + if (exitcode) { + error("delaunayn: qhull failed."); + return retval; + } + + // triangulate non-simplicial facets - facetT *facet; - vertexT *vertex, **vertexp; - int nf=0,i=0; + qh_triangulate(); + + facetT *facet; + vertexT *vertex, **vertexp; + int nf=0,i=0; + + FORALLfacets { + if (!facet->upperdelaunay) nf++; - FORALLfacets { - if (!facet->upperdelaunay) nf++; + // Double check + if (!facet->simplicial) { + error("delaunayn: Qhull returned non-simplicial facets. Try delaunayn with different options."); + break; } + } + if (!error_state) { Matrix simpl(nf,dim+1); FORALLfacets { if (!facet->upperdelaunay) { int j=0; FOREACHvertex_ (facet->vertices) { + + // if delaunayn crashes, enable this check + +# if 0 + if (j > dim) { + error("delaunayn: internal error. Qhull returned non-simplicial facets."); + return retval; + } +# endif + simpl(i,j++)=1 + qh_pointid(vertex->point); } i++; @@ -121,16 +193,18 @@ } retval(0) = simpl; } + + qh_freeqhull(!qh_ALL); - //free long memory + //free long memory int curlong, totlong; qh_memfreeshort (&curlong, &totlong); - //free short memory and memory allocator + //free short memory and memory allocator if (curlong || totlong) { - warning("delaunay: did not free %d bytes of long memory (%d pieces)", - totlong, curlong); + warning("delaunay: did not free %d bytes of long memory (%d pieces)", + totlong, curlong); } } else if (n == dim + 1) { // one should check if nx points span a simplex