__delaunayn__.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2000-2012 Kai Habel
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 /*
00024   16. July 2000 - Kai Habel: first release
00025 
00026   25. September 2002 - Changes by Rafael Laboissiere <rafael@laboissiere.net>
00027 
00028   * Added Qbb option to normalize the input and avoid crashes in Octave.
00029   * delaunayn accepts now a second (optional) argument that must be a string
00030   containing extra options to the qhull command.
00031   * Fixed doc string.  The dimension of the result matrix is [m, dim+1], and
00032   not [n, dim-1].
00033 
00034   6. June 2006: Changes by Alexander Barth <abarth@marine.usf.edu>
00035 
00036   * triangulate non-simplicial facets
00037   * allow options to be specified as cell array of strings
00038   * change the default options (for compatibility with matlab)
00039 */
00040 
00041 #ifdef HAVE_CONFIG_H
00042 #include <config.h>
00043 #endif
00044 
00045 #include <iostream>
00046 #include <string>
00047 
00048 #include "Cell.h"
00049 #include "defun-dld.h"
00050 #include "error.h"
00051 #include "oct-obj.h"
00052 #include "unwind-prot.h"
00053 
00054 #if defined (HAVE_QHULL)
00055 # include "oct-qhull.h"
00056 # if defined (NEED_QHULL_VERSION)
00057 char qh_version[] = "__delaunayn__.oct 2007-08-21";
00058 # endif
00059 #endif
00060 
00061 static void
00062 close_fcn (FILE *f)
00063 {
00064   gnulib::fclose (f);
00065 }
00066 
00067 DEFUN_DLD (__delaunayn__, args, ,
00068            "-*- texinfo -*-\n\
00069 @deftypefn  {Loadable Function} {@var{T} =} __delaunayn__ (@var{pts})\n\
00070 @deftypefnx {Loadable Function} {@var{T} =} __delaunayn__ (@var{pts}, @var{options})\n\
00071 Undocumented internal function.\n\
00072 @end deftypefn")
00073 
00074 {
00075   octave_value_list retval;
00076 
00077 #if defined (HAVE_QHULL)
00078 
00079   retval(0) = 0.0;
00080 
00081   int nargin = args.length ();
00082   if (nargin < 1 || nargin > 2)
00083     {
00084       print_usage ();
00085       return retval;
00086     }
00087 
00088   Matrix p (args(0).matrix_value ());
00089   const octave_idx_type dim = p.columns ();
00090   const octave_idx_type n = p.rows ();
00091 
00092   // Default options
00093   std::string options;
00094   if (dim <= 3)
00095     options = "Qt Qbb Qc Qz";
00096   else
00097     options = "Qt Qbb Qc Qx";
00098 
00099   if (nargin == 2)
00100     {
00101       if (args(1).is_string ())
00102         options = args(1).string_value ();
00103       else if (args(1).is_empty ())
00104         ;  // Use default options
00105       else if (args(1).is_cellstr ())
00106         {
00107           options = "";
00108           Array<std::string> tmp = args(1).cellstr_value ();
00109 
00110           for (octave_idx_type i = 0; i < tmp.numel (); i++)
00111             options += tmp(i) + " ";
00112         }
00113       else
00114         {
00115           error ("__delaunayn__: OPTIONS argument must be a string, cell array of strings, or empty");
00116           return retval;
00117         }
00118     }
00119 
00120   if (n > dim + 1)
00121     {
00122       p = p.transpose ();
00123       double *pt_array = p.fortran_vec ();
00124       boolT ismalloc = false;
00125 
00126       // Qhull flags argument is not const char*
00127       OCTAVE_LOCAL_BUFFER (char, flags, 9 + options.length());
00128 
00129       sprintf (flags, "qhull d %s", options.c_str ());
00130 
00131       unwind_protect frame;
00132 
00133       // Replace the outfile pointer with stdout for debugging information.
00134 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)
00135       FILE *outfile = gnulib::fopen ("NUL", "w");
00136 #else
00137       FILE *outfile = gnulib::fopen ("/dev/null", "w");
00138 #endif
00139       FILE *errfile = stderr;
00140 
00141       if (outfile)
00142         frame.add_fcn (close_fcn, outfile);
00143       else
00144         {
00145           error ("__delaunayn__: unable to create temporary file for output");
00146           return retval;
00147         }
00148 
00149       int exitcode = qh_new_qhull (dim, n, pt_array, 
00150                                    ismalloc, flags, outfile, errfile);
00151       if (! exitcode)
00152         {
00153           // triangulate non-simplicial facets
00154           qh_triangulate ();
00155 
00156           facetT *facet;
00157           vertexT *vertex, **vertexp;
00158           octave_idx_type nf = 0, i = 0;
00159 
00160           FORALLfacets
00161             {
00162               if (! facet->upperdelaunay)
00163                 nf++;
00164 
00165               // Double check.  Non-simplicial facets will cause segfault below
00166               if (! facet->simplicial)
00167                 {
00168                   error ("__delaunayn__: Qhull returned non-simplicial facets -- try delaunayn with different options");
00169                   exitcode = 1;
00170                   break;
00171                 }
00172             }
00173 
00174           if (! exitcode)
00175             {
00176               Matrix simpl (nf, dim+1);
00177 
00178               FORALLfacets
00179                 {
00180                   if (! facet->upperdelaunay)
00181                     {
00182                       octave_idx_type j = 0;
00183 
00184                       FOREACHvertex_ (facet->vertices)
00185                         {
00186                           simpl(i, j++) = 1 + qh_pointid(vertex->point);
00187                         }
00188                       i++;
00189                     }
00190                 }
00191 
00192               retval(0) = simpl;
00193             }
00194         }
00195       else
00196         error ("__delaunayn__: qhull failed");
00197 
00198       // Free memory from Qhull
00199       qh_freeqhull (! qh_ALL);
00200 
00201       int curlong, totlong;
00202       qh_memfreeshort (&curlong, &totlong);
00203 
00204       if (curlong || totlong)
00205         warning ("__delaunay__: did not free %d bytes of long memory (%d pieces)",
00206                  totlong, curlong);
00207     }
00208   else if (n == dim + 1)
00209     {
00210       // one should check if nx points span a simplex
00211       // I will look at this later.
00212       RowVector vec (n);
00213       for (octave_idx_type i = 0; i < n; i++)
00214         vec(i) = i + 1.0;
00215 
00216       retval(0) = vec;
00217     }
00218 
00219 #else
00220   error ("__delaunayn__: not available in this version of Octave");
00221 #endif
00222 
00223   return retval;
00224 }
00225 
00226 /*
00227 
00228 ## No test needed for internal helper function.
00229 %!assert (1)
00230 
00231 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines