GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
__delaunayn__.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2000-2013 Kai Habel
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 /*
24  16. July 2000 - Kai Habel: first release
25 
26  25. September 2002 - Changes by Rafael Laboissiere <rafael@laboissiere.net>
27 
28  * Added Qbb option to normalize the input and avoid crashes in Octave.
29  * delaunayn accepts now a second (optional) argument that must be a string
30  containing extra options to the qhull command.
31  * Fixed doc string. The dimension of the result matrix is [m, dim+1], and
32  not [n, dim-1].
33 
34  6. June 2006: Changes by Alexander Barth <abarth@marine.usf.edu>
35 
36  * triangulate non-simplicial facets
37  * allow options to be specified as cell array of strings
38  * change the default options (for compatibility with matlab)
39 */
40 
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44 
45 #include <iostream>
46 #include <string>
47 
48 #include "Cell.h"
49 #include "defun-dld.h"
50 #include "error.h"
51 #include "oct-obj.h"
52 #include "unwind-prot.h"
53 
54 #if defined (HAVE_QHULL)
55 # include "oct-qhull.h"
56 # if defined (NEED_QHULL_VERSION)
57 char qh_version[] = "__delaunayn__.oct 2007-08-21";
58 # endif
59 #endif
60 
61 static void
62 close_fcn (FILE *f)
63 {
64  gnulib::fclose (f);
65 }
66 
67 static bool
69 {
70  if (sizeof (octave_idx_type) > sizeof (int))
71  {
72  int maxval = std::numeric_limits<int>::max ();
73 
74  if (dim > maxval || n > maxval)
75  {
76  error ("%s: dimension too large for Qhull", who);
77  return false;
78  }
79  }
80 
81  return true;
82 }
83 
84 DEFUN_DLD (__delaunayn__, args, ,
85  "-*- texinfo -*-\n\
86 @deftypefn {Loadable Function} {@var{T} =} __delaunayn__ (@var{pts})\n\
87 @deftypefnx {Loadable Function} {@var{T} =} __delaunayn__ (@var{pts}, @var{options})\n\
88 Undocumented internal function.\n\
89 @end deftypefn")
90 
91 {
92  octave_value_list retval;
93 
94 #if defined (HAVE_QHULL)
95 
96  retval(0) = 0.0;
97 
98  int nargin = args.length ();
99  if (nargin < 1 || nargin > 2)
100  {
101  print_usage ();
102  return retval;
103  }
104 
105  Matrix p (args(0).matrix_value ());
106  const octave_idx_type dim = p.columns ();
107  const octave_idx_type n = p.rows ();
108 
109  if (! octave_qhull_dims_ok (dim, n, "__delaynayn__"))
110  return retval;
111 
112  // Default options
113  std::string options;
114  if (dim <= 3)
115  options = "Qt Qbb Qc Qz";
116  else
117  options = "Qt Qbb Qc Qx";
118 
119  if (nargin == 2)
120  {
121  if (args(1).is_string ())
122  options = args(1).string_value ();
123  else if (args(1).is_empty ())
124  ; // Use default options
125  else if (args(1).is_cellstr ())
126  {
127  options = "";
128  Array<std::string> tmp = args(1).cellstr_value ();
129 
130  for (octave_idx_type i = 0; i < tmp.numel (); i++)
131  options += tmp(i) + " ";
132  }
133  else
134  {
135  error ("__delaunayn__: OPTIONS argument must be a string, cell array of strings, or empty");
136  return retval;
137  }
138  }
139 
140  if (n > dim + 1)
141  {
142  p = p.transpose ();
143  double *pt_array = p.fortran_vec ();
144  boolT ismalloc = false;
145 
146  // Qhull flags argument is not const char*
147  OCTAVE_LOCAL_BUFFER (char, flags, 9 + options.length ());
148 
149  sprintf (flags, "qhull d %s", options.c_str ());
150 
151  unwind_protect frame;
152 
153  // Replace the outfile pointer with stdout for debugging information.
154 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)
155  FILE *outfile = gnulib::fopen ("NUL", "w");
156 #else
157  FILE *outfile = gnulib::fopen ("/dev/null", "w");
158 #endif
159  FILE *errfile = stderr;
160 
161  if (outfile)
162  frame.add_fcn (close_fcn, outfile);
163  else
164  {
165  error ("__delaunayn__: unable to create temporary file for output");
166  return retval;
167  }
168 
169  int exitcode = qh_new_qhull (dim, n, pt_array,
170  ismalloc, flags, outfile, errfile);
171  if (! exitcode)
172  {
173  // triangulate non-simplicial facets
174  qh_triangulate ();
175 
176  facetT *facet;
177  vertexT *vertex, **vertexp;
178  octave_idx_type nf = 0, i = 0;
179 
180  FORALLfacets
181  {
182  if (! facet->upperdelaunay)
183  nf++;
184 
185  // Double check. Non-simplicial facets will cause segfault below
186  if (! facet->simplicial)
187  {
188  error ("__delaunayn__: Qhull returned non-simplicial facets -- try delaunayn with different options");
189  exitcode = 1;
190  break;
191  }
192  }
193 
194  if (! exitcode)
195  {
196  Matrix simpl (nf, dim+1);
197 
198  FORALLfacets
199  {
200  if (! facet->upperdelaunay)
201  {
202  octave_idx_type j = 0;
203 
204  FOREACHvertex_ (facet->vertices)
205  {
206  simpl(i, j++) = 1 + qh_pointid(vertex->point);
207  }
208  i++;
209  }
210  }
211 
212  retval(0) = simpl;
213  }
214  }
215  else
216  error ("__delaunayn__: qhull failed");
217 
218  // Free memory from Qhull
219  qh_freeqhull (! qh_ALL);
220 
221  int curlong, totlong;
222  qh_memfreeshort (&curlong, &totlong);
223 
224  if (curlong || totlong)
225  warning ("__delaunay__: did not free %d bytes of long memory (%d pieces)",
226  totlong, curlong);
227  }
228  else if (n == dim + 1)
229  {
230  // one should check if nx points span a simplex
231  // I will look at this later.
232  RowVector vec (n);
233  for (octave_idx_type i = 0; i < n; i++)
234  vec(i) = i + 1.0;
235 
236  retval(0) = vec;
237  }
238 
239 #else
240  error ("__delaunayn__: not available in this version of Octave");
241 #endif
242 
243  return retval;
244 }
245 
246 /*
247 ## No test needed for internal helper function.
248 %!assert (1)
249 */