changelog shortlog tags changeset files revisions annotate raw

src/DLD-FUNCTIONS/convhulln.cc

changeset 9846: 1d90fc211872
parent:eb63fbe60fab
author: John W. Eaton <jwe@octave.org>
date: Sat Nov 21 21:44:51 2009 -0500 (33 hours ago)
permissions: -rw-r--r--
description: configure.ac: report freetype, fontconfig, and fltk cflags and libs info
1/*
2
3Copyright (C) 2000, 2007, 2008, 2009 Kai Habel
4
5This file is part of Octave.
6
7Octave is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by the
9Free Software Foundation; either version 3 of the License, or (at your
10option) any later version.
11
12Octave is distributed in the hope that it will be useful, but WITHOUT
13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with Octave; see the file COPYING. If not, see
19<http://www.gnu.org/licenses/>.
20
21*/
22
23/*
2429. July 2000 - Kai Habel: first release
252002-04-22 Paul Kienzle
26* Use warning(...) function rather than writing to cerr
272006-05-01 Tom Holroyd
28* add support for consistent winding in all dimensions; output is
29* guaranteed to be simplicial.
30*/
31
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36#include <sstream>
37
38#include "Cell.h"
39#include "defun-dld.h"
40#include "error.h"
41#include "oct-obj.h"
42#include "parse.h"
43
44#ifdef HAVE_QHULL
45#if defined(HAVE__SNPRINTF) && !defined(HAVE_SNPRINTF)
46#define snprintf _snprintf
47#endif
48
49extern "C" {
50#include <qhull/qhull_a.h>
51}
52
53#ifdef NEED_QHULL_VERSION
54char qh_version[] = "convhulln.oct 2007-07-24";
55#endif
56#endif
57
58DEFUN_DLD (convhulln, args, nargout,
59 "-*- texinfo -*-\n\
60@deftypefn {Loadable Function} {@var{h} =} convhulln (@var{p})\n\
61@deftypefnx {Loadable Function} {@var{h} =} convhulln (@var{p}, @var{opt})\n\
62@deftypefnx {Loadable Function} {[@var{h}, @var{v}] =} convhulln (@dots{})\n\
63Return an index vector to the points of the enclosing convex hull.\n\
64The input matrix of size [n, dim] contains n points of dimension dim.\n\n\
65If a second optional argument is given, it must be a string or cell array\n\
66of strings containing options for the underlying qhull command. (See\n\
67the Qhull documentation for the available options.) The default options\n\
68are \"s Qci Tcv\".\n\
69If the second output @var{V} is requested the volume of the convex hull is\n\
70calculated.\n\n\
71@seealso{convhull, delaunayn}\n\
72@end deftypefn")
73{
74 octave_value_list retval;
75
76#ifdef HAVE_QHULL
77 std::string options;
78
79 int nargin = args.length ();
80 if (nargin < 1 || nargin > 2)
81 {
82 print_usage ();
83 return retval;
84 }
85
86 if (nargin == 2)
87 {
88 if (args (1).is_string ())
89 options = args(1).string_value ();
90 else if (args(1).is_cell ())
91 {
92 Cell c = args(1).cell_value ();
93 options = "";
94 for (octave_idx_type i = 0; i < c.numel (); i++)
95 {
96 if (! c.elem(i).is_string ())
97 {
98 error ("convhulln: second argument must be a string or cell array of strings");
99 return retval;
100 }
101
102 options = options + c.elem(i).string_value() + " ";
103 }
104 }
105 else
106 {
107 error ("convhulln: second argument must be a string or cell array of strings");
108 return retval;
109 }
110 }
111 else
112 // turn on some consistency checks
113 options = "s Qci Tcv";
114
115 Matrix p (args(0).matrix_value ());
116
117 const octave_idx_type dim = p.columns ();
118 const octave_idx_type n = p.rows ();
119 p = p.transpose ();
120
121 double *pt_array = p.fortran_vec ();
122
123 boolT ismalloc = False;
124
125 OCTAVE_LOCAL_BUFFER (char, flags, 250);
126
127 // hmm, lots of options for qhull here
128 // QJ guarantees that the output will be triangles
129 snprintf (flags, 250, "qhull QJ %s", options.c_str ());
130
131 if (! qh_new_qhull (dim, n, pt_array, ismalloc, flags, 0, stderr))
132 {
133 // If you want some debugging information replace the NULL
134 // pointer with stdout
135
136 vertexT *vertex, **vertexp;
137 facetT *facet;
138 setT *vertices;
139 unsigned int nf = qh num_facets;
140
141 Matrix idx (nf, dim);
142
143 octave_idx_type j, i = 0;
144 FORALLfacets
145 {
146 j = 0;
147 if (! facet->simplicial)
148 // should never happen with QJ
149 error ("convhulln: non-simplicial facet");
150
151 if (dim == 3)
152 {
153 vertices = qh_facet3vertex (facet);
154 FOREACHvertex_ (vertices)
155 idx(i, j++) = 1 + qh_pointid(vertex->point);
156 qh_settempfree (&vertices);
157 }
158 else
159 {
160 if (facet->toporient ^ qh_ORIENTclock)
161 {
162 FOREACHvertex_ (facet->vertices)
163 idx(i, j++) = 1 + qh_pointid(vertex->point);
164 }
165 else
166 {
167 FOREACHvertexreverse12_ (facet->vertices)
168 idx(i, j++) = 1 + qh_pointid(vertex->point);
169 }
170 }
171 if (j < dim)
172 // likewise but less fatal
173 warning ("facet %d only has %d vertices", i, j);
174 i++;
175 }
176
177 if (nargout == 2)
178 // calculate volume of convex hull
179 // taken from qhull src/geom2.c
180 {
181 realT area;
182 realT dist;
183
184 FORALLfacets
185 {
186 if (! facet->normal)
187 continue;
188
189 if (facet->upperdelaunay && qh ATinfinity)
190 continue;
191
192 facet->f.area = area = qh_facetarea (facet);
193 facet->isarea = True;
194
195 if (qh DELAUNAY)
196 {
197 if (facet->upperdelaunay == qh UPPERdelaunay)
198 qh totarea += area;
199 }
200 else
201 {
202 qh totarea += area;
203 qh_distplane (qh interior_point, facet, &dist);
204 qh totvol += -dist * area/ qh hull_dim;
205 }
206 }
207
208 retval(1) = octave_value (qh totvol);
209 }
210
211 retval(0) = octave_value (idx);
212 }
213
214 // free long memory
215 qh_freeqhull (! qh_ALL);
216
217 // free short memory and memory allocator
218 int curlong, totlong;
219 qh_memfreeshort (&curlong, &totlong);
220
221 if (curlong || totlong)
222 warning ("convhulln: did not free %d bytes of long memory (%d pieces)",
223 totlong, curlong);
224#else
225 error ("convhulln: not available in this version of Octave");
226#endif
227
228 return retval;
229}
230
231/*
232%!test
233%! cube = [0 0 0;1 0 0;1 1 0;0 1 0;0 0 1;1 0 1;1 1 1;0 1 1];
234%! [h, v] = convhulln(cube,'Pp');
235%! assert (v, 1.0, 1e6*eps);
236%!test
237%! tetrahedron = [1 1 1;-1 -1 1;-1 1 -1;1 -1 -1];
238%! [h, v] = convhulln(tetrahedron,'Pp');
239%! assert (v, 8/3, 1e6*eps);
240*/