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