__voronoi__.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 20. Augiust 2000 - Kai Habel: first release
00025 */
00026 
00027 /*
00028 2003-12-14 Rafael Laboissiere <rafael@laboissiere.net>
00029 Added optional second argument to pass options to the underlying
00030 qhull command
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         ; // Use default options.
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   // Replace the outfile pointer with stdout for debugging information.
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   // qh_new_qhull command and points arguments are not const...
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       // Calling findgood_all provides the number of Voronoi vertices
00156       // (sets qh num_good).
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       // Find the voronoi centers for all facets.
00166 
00167       qh_setvoronoi_all ();
00168 
00169       facetT *facet;
00170       vertexT *vertex;
00171       octave_idx_type k;
00172 
00173       // Find the number of Voronoi vertices for each Voronoi cell and
00174       // store them in NI so we can use them later to set the dimensions
00175       // of the RowVector objects used to collect them.
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       // If Qhull finds fewer regions than points, we will pad the end
00218       // of the at_inf and C arrays so that they always contain at least
00219       // as many elements as the given points array.
00220 
00221       // FIXME -- is it possible (or does it make sense) for
00222       // num_voronoi_regions to ever be larger than num_points?
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       // The list of Voronoi vertices.  The first element is always
00230       // Inf.
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       // The cell array of vectors of indices into F that represent the
00237       // vertices of the Voronoi regions (cells).
00238 
00239       Cell C (nr, 1);
00240 
00241       // Now loop through the list of vertices again and store the
00242       // coordinates of the Voronoi vertices and the lists of indices
00243       // for the cells.
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           // Qhull seems to sometimes produces regions with a single
00265           // vertex.  Is that a bug?  How can a region have just one
00266           // vertex?  Let's skip it.
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   // Free memory from Qhull
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 ## No test needed for internal helper function.
00334 %!assert (1)
00335 
00336 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines