GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
__delaunayn__.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2000-2018 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
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License 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 <https://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 #if defined (HAVE_CONFIG_H)
42 # include "config.h"
43 #endif
44 
45 #include <cstdio>
46 
47 #include <limits>
48 #include <string>
49 
50 #include "Array.h"
51 #include "dMatrix.h"
52 #include "dRowVector.h"
53 #include "oct-locbuf.h"
54 #include "unwind-prot.h"
55 
56 #include "defun-dld.h"
57 #include "error.h"
58 #include "errwarn.h"
59 #include "ovl.h"
60 
61 #if defined (HAVE_QHULL)
62 
63 # include "oct-qhull.h"
64 
65 # if defined (NEED_QHULL_VERSION)
66 char qh_version[] = "__delaunayn__.oct 2007-08-21";
67 # endif
68 
69 static void
70 close_fcn (FILE *f)
71 {
72  std::fclose (f);
73 }
74 
75 static void
77 {
78  qh_freeqhull (! qh_ALL);
79 
80  int curlong, totlong;
81  qh_memfreeshort (&curlong, &totlong);
82 
83  if (curlong || totlong)
84  warning ("__delaunayn__: did not free %d bytes of long memory (%d pieces)",
85  totlong, curlong);
86 }
87 
88 static bool
90 {
91  if (sizeof (octave_idx_type) > sizeof (int))
92  {
93  int maxval = std::numeric_limits<int>::max ();
94 
95  if (dim > maxval || n > maxval)
96  error ("%s: dimension too large for Qhull", who);
97  }
98 
99  return true;
100 }
101 
102 #endif
103 
104 DEFUN_DLD (__delaunayn__, args, ,
105  doc: /* -*- texinfo -*-
106 @deftypefn {} {@var{T} =} __delaunayn__ (@var{pts})
107 @deftypefnx {} {@var{T} =} __delaunayn__ (@var{pts}, @var{options})
108 Undocumented internal function.
109 @end deftypefn */)
110 
111 {
112 #if defined (HAVE_QHULL)
113 
114  int nargin = args.length ();
115 
117  print_usage ();
118 
120 
121  retval(0) = 0.0;
122 
123  Matrix p (args(0).matrix_value ());
124  const octave_idx_type dim = p.columns ();
125  const octave_idx_type n = p.rows ();
126 
127  if (! octave_qhull_dims_ok (dim, n, "__delaynayn__"))
128  return retval;
129 
130  // Default options
132  if (dim <= 3)
133  options = "Qt Qbb Qc Qz";
134  else
135  options = "Qt Qbb Qc Qx";
136 
137  if (nargin == 2)
138  {
139  if (args(1).is_string ())
140  options = args(1).string_value ();
141  else if (args(1).isempty ())
142  ; // Use default options
143  else if (args(1).iscellstr ())
144  {
145  options = "";
146  Array<std::string> tmp = args(1).cellstr_value ();
147 
148  for (octave_idx_type i = 0; i < tmp.numel (); i++)
149  options += tmp(i) + ' ';
150  }
151  else
152  error ("__delaunayn__: OPTIONS argument must be a string, cell array of strings, or empty");
153  }
154 
155  if (n > dim + 1)
156  {
157  p = p.transpose ();
158  double *pt_array = p.fortran_vec ();
159  boolT ismalloc = false;
160 
161  // Qhull flags argument is not const char*
162  OCTAVE_LOCAL_BUFFER (char, flags, 9 + options.length ());
163 
164  sprintf (flags, "qhull d %s", options.c_str ());
165 
167 
168  // Replace the outfile pointer with stdout for debugging information.
169 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)
170  FILE *outfile = std::fopen ("NUL", "w");
171 #else
172  FILE *outfile = std::fopen ("/dev/null", "w");
173 #endif
174  FILE *errfile = stderr;
175 
176  if (! outfile)
177  error ("__delaunayn__: unable to create temporary file for output");
178 
179  frame.add_fcn (close_fcn, outfile);
180 
181  int exitcode = qh_new_qhull (dim, n, pt_array,
182  ismalloc, flags, outfile, errfile);
183 
185 
186  if (exitcode)
187  error ("__delaunayn__: qhull failed");
188 
189  // triangulate non-simplicial facets
190  qh_triangulate ();
191 
192  facetT *facet;
193  vertexT *vertex, **vertexp;
194  octave_idx_type nf = 0;
195  octave_idx_type i = 0;
196 
197  FORALLfacets
198  {
199  if (! facet->upperdelaunay)
200  nf++;
201 
202  // Double check. Non-simplicial facets will cause segfault below
203  if (! facet->simplicial)
204  error ("__delaunayn__: Qhull returned non-simplicial facets -- try delaunayn with different options");
205  }
206 
207  if (! exitcode)
208  {
209  Matrix simpl (nf, dim+1);
210 
211  FORALLfacets
212  {
213  if (! facet->upperdelaunay)
214  {
215  octave_idx_type j = 0;
216 
217  FOREACHvertex_ (facet->vertices)
218  {
219  simpl(i, j++) = 1 + qh_pointid(vertex->point);
220  }
221  i++;
222  }
223  }
224 
225  retval(0) = simpl;
226  }
227  }
228  else if (n == dim + 1)
229  {
230  // FIXME: 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  return retval;
240 
241 #else
242 
243  octave_unused_parameter (args);
244 
245  err_disabled_feature ("__delaunayn__", "Qhull");
246 
247 #endif
248 }
249 
250 /*
251 ## No test needed for internal helper function.
252 %!assert (1)
253 */
static void free_qhull_memory()
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE * f
void add_fcn(void(*fcn)(void))
void error(const char *fmt,...)
Definition: error.cc:578
static void close_fcn(FILE *f)
OCTAVE_EXPORT octave_value_list or both For fclose
Definition: file-io.cc:676
double tmp
Definition: data.cc:6252
octave_value retval
Definition: data.cc:6246
Definition: dMatrix.h:36
OCTAVE_EXPORT octave_value_list iscellstr
Definition: ov-cell.cc:1220
void warning(const char *fmt,...)
Definition: error.cc:801
octave::unwind_protect frame
Definition: graphics.cc:12190
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:227
p
Definition: lu.cc:138
OCTAVE_EXPORT octave_value_list only variables visible in the local scope are displayed The following are valid options
Definition: variables.cc:1862
octave_idx_type length(void) const
Definition: ovl.h:96
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:41
static bool octave_qhull_dims_ok(octave_idx_type dim, octave_idx_type n, const char *who)
args.length() nargin
Definition: file-io.cc:589
for i
Definition: data.cc:5264
#define DEFUN_DLD(name, args_name, nargout_name, doc)
Macro to define an at run time dynamically loadable builtin function.
Definition: defun-dld.h:58
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
Definition: errwarn.cc:50
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888