Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifdef HAVE_CONFIG_H
00034 #include <config.h>
00035 #endif
00036
00037 #include <cstdio>
00038
00039 #include <list>
00040
00041 #include "lo-ieee.h"
00042
00043 #include "Cell.h"
00044 #include "defun-dld.h"
00045 #include "error.h"
00046 #include "oct-obj.h"
00047 #include "unwind-prot.h"
00048
00049 #if defined (HAVE_QHULL)
00050 # include "oct-qhull.h"
00051 # if defined (NEED_QHULL_VERSION)
00052 char qh_version[] = "__voronoi__.oct 2007-07-24";
00053 # endif
00054 #endif
00055
00056 static void
00057 close_fcn (FILE *f)
00058 {
00059 gnulib::fclose (f);
00060 }
00061
00062 DEFUN_DLD (__voronoi__, args, ,
00063 "-*- texinfo -*-\n\
00064 @deftypefn {Loadable Function} {@var{C}, @var{F} =} __voronoi__ (@var{caller}, @var{pts})\n\
00065 @deftypefnx {Loadable Function} {@var{C}, @var{F} =} __voronoi__ (@var{caller}, @var{pts}, @var{options})\n\
00066 @deftypefnx {Loadable Function} {@var{C}, @var{F}, @var{Inf_Pts} =} __voronoi__ (@dots{})\n\
00067 Undocumented internal function.\n\
00068 @end deftypefn")
00069 {
00070 octave_value_list retval;
00071
00072 std::string caller = args(0).string_value ();
00073
00074 #if defined (HAVE_QHULL)
00075
00076 retval(0) = 0.0;
00077
00078 int nargin = args.length ();
00079 if (nargin < 2 || nargin > 3)
00080 {
00081 print_usage ();
00082 return retval;
00083 }
00084
00085 Matrix points = args(1).matrix_value ();
00086 const octave_idx_type dim = points.columns ();
00087 const octave_idx_type num_points = points.rows ();
00088
00089 points = points.transpose ();
00090
00091 std::string options;
00092
00093 if (dim <= 4)
00094 options = " Qbb";
00095 else
00096 options = " Qbb Qx";
00097
00098 if (nargin == 3)
00099 {
00100 octave_value opt_arg = args(2);
00101
00102 if (opt_arg.is_string ())
00103 options = " " + opt_arg.string_value ();
00104 else if (opt_arg.is_empty ())
00105 ;
00106 else if (opt_arg.is_cellstr ())
00107 {
00108 options = "";
00109
00110 Array<std::string> tmp = opt_arg.cellstr_value ();
00111
00112 for (octave_idx_type i = 0; i < tmp.numel (); i++)
00113 options += " " + tmp(i);
00114 }
00115 else
00116 {
00117 error ("%s: OPTIONS must be a string, cell array of strings, or empty",
00118 caller.c_str ());
00119 return retval;
00120 }
00121 }
00122
00123 boolT ismalloc = false;
00124
00125 unwind_protect frame;
00126
00127
00128 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)
00129 FILE *outfile = gnulib::fopen ("NUL", "w");
00130 #else
00131 FILE *outfile = gnulib::fopen ("/dev/null", "w");
00132 #endif
00133 FILE *errfile = stderr;
00134
00135 if (outfile)
00136 frame.add_fcn (close_fcn, outfile);
00137 else
00138 {
00139 error ("__voronoi__: unable to create temporary file for output");
00140 return retval;
00141 }
00142
00143
00144
00145 std::string cmd = "qhull v" + options;
00146
00147 OCTAVE_LOCAL_BUFFER (char, cmd_str, cmd.length () + 1);
00148
00149 strcpy (cmd_str, cmd.c_str ());
00150
00151 int exitcode = qh_new_qhull (dim, num_points, points.fortran_vec (),
00152 ismalloc, cmd_str, outfile, errfile);
00153 if (! exitcode)
00154 {
00155
00156
00157
00158 qh_findgood_all (qh facet_list);
00159
00160 octave_idx_type num_voronoi_regions
00161 = qh num_vertices - qh_setsize (qh del_vertices);
00162
00163 octave_idx_type num_voronoi_vertices = qh num_good;
00164
00165
00166
00167 qh_setvoronoi_all ();
00168
00169 facetT *facet;
00170 vertexT *vertex;
00171 octave_idx_type k;
00172
00173
00174
00175
00176
00177 FORALLfacets
00178 {
00179 facet->seen = false;
00180 }
00181
00182 OCTAVE_LOCAL_BUFFER (octave_idx_type, ni, num_voronoi_regions);
00183 for (octave_idx_type i = 0; i < num_voronoi_regions; i++)
00184 ni[i] = 0;
00185
00186 k = 0;
00187
00188 FORALLvertices
00189 {
00190 if (qh hull_dim == 3)
00191 qh_order_vertexneighbors (vertex);
00192
00193 bool infinity_seen = false;
00194
00195 facetT *neighbor, **neighborp;
00196
00197 FOREACHneighbor_ (vertex)
00198 {
00199 if (neighbor->upperdelaunay)
00200 {
00201 if (! infinity_seen)
00202 {
00203 infinity_seen = true;
00204 ni[k]++;
00205 }
00206 }
00207 else
00208 {
00209 neighbor->seen = true;
00210 ni[k]++;
00211 }
00212 }
00213
00214 k++;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224 octave_idx_type nr = (num_points > num_voronoi_regions
00225 ? num_points : num_voronoi_regions);
00226
00227 boolMatrix at_inf (nr, 1, false);
00228
00229
00230
00231 Matrix F (num_voronoi_vertices+1, dim);
00232
00233 for (octave_idx_type d = 0; d < dim; d++)
00234 F(0,d) = octave_Inf;
00235
00236
00237
00238
00239 Cell C (nr, 1);
00240
00241
00242
00243
00244
00245 FORALLfacets
00246 {
00247 facet->seen = false;
00248 }
00249
00250 octave_idx_type i = 0;
00251 k = 0;
00252
00253 FORALLvertices
00254 {
00255 if (qh hull_dim == 3)
00256 qh_order_vertexneighbors (vertex);
00257
00258 bool infinity_seen = false;
00259
00260 octave_idx_type idx = qh_pointid (vertex->point);
00261
00262 octave_idx_type num_vertices = ni[k++];
00263
00264
00265
00266
00267
00268 if (num_vertices == 1)
00269 continue;
00270
00271 RowVector facet_list (num_vertices);
00272
00273 octave_idx_type m = 0;
00274
00275 facetT *neighbor, **neighborp;
00276
00277 FOREACHneighbor_(vertex)
00278 {
00279 if (neighbor->upperdelaunay)
00280 {
00281 if (! infinity_seen)
00282 {
00283 infinity_seen = true;
00284 facet_list(m++) = 1;
00285 at_inf(idx) = true;
00286 }
00287 }
00288 else
00289 {
00290 if (! neighbor->seen)
00291 {
00292 i++;
00293 for (octave_idx_type d = 0; d < dim; d++)
00294 F(i,d) = neighbor->center[d];
00295
00296 neighbor->seen = true;
00297 neighbor->visitid = i;
00298 }
00299
00300 facet_list(m++) = neighbor->visitid + 1;
00301 }
00302 }
00303
00304 C(idx) = facet_list;
00305 }
00306
00307 retval(2) = at_inf;
00308 retval(1) = C;
00309 retval(0) = F;
00310 }
00311 else
00312 error ("%s: qhull failed", caller.c_str ());
00313
00314
00315 qh_freeqhull (! qh_ALL);
00316
00317 int curlong, totlong;
00318 qh_memfreeshort (&curlong, &totlong);
00319
00320 if (curlong || totlong)
00321 warning ("%s: qhull did not free %d bytes of long memory (%d pieces)",
00322 caller.c_str (), totlong, curlong);
00323
00324 #else
00325 error ("%s: not available in this version of Octave", caller.c_str ());
00326 #endif
00327
00328 return retval;
00329 }
00330
00331
00332
00333
00334
00335
00336