svn-gvsig-desktop / trunk / extensions / extGraph / src / org / gvsig / fmap / algorithm / triangulation / visad / DelaunayClarkson.java @ 39203
History | View | Annotate | Download (42.8 KB)
1 |
//
|
---|---|
2 |
// DelaunayClarkson.java
|
3 |
//
|
4 |
|
5 |
/*
|
6 |
VisAD system for interactive analysis and visualization of numerical
|
7 |
data. Copyright (C) 1996 - 2002 Bill Hibbard, Curtis Rueden, Tom
|
8 |
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
|
9 |
Tommy Jasmin.
|
10 |
|
11 |
This library is free software; you can redistribute it and/or
|
12 |
modify it under the terms of the GNU Library General Public
|
13 |
License as published by the Free Software Foundation; either
|
14 |
version 2 of the License, or (at your option) any later version.
|
15 |
|
16 |
This library is distributed in the hope that it will be useful,
|
17 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
19 |
Library General Public License for more details.
|
20 |
|
21 |
You should have received a copy of the GNU Library General Public
|
22 |
License along with this library; if not, write to the Free
|
23 |
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
24 |
MA 02111-1307, USA
|
25 |
*/
|
26 |
|
27 |
package org.gvsig.fmap.algorithm.triangulation.visad; |
28 |
|
29 |
|
30 |
/* The Delaunay triangulation algorithm in this class
|
31 |
* is originally from hull by Ken Clarkson:
|
32 |
*
|
33 |
* Ken Clarkson wrote this. Copyright (c) 1995 by AT&T..
|
34 |
* Permission to use, copy, modify, and distribute this software for any
|
35 |
* purpose without fee is hereby granted, provided that this entire notice
|
36 |
* is included in all copies of any software which is or includes a copy
|
37 |
* or modification of this software and in all copies of the supporting
|
38 |
* documentation for such software.
|
39 |
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
40 |
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
|
41 |
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
42 |
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
43 |
*/
|
44 |
|
45 |
/**
|
46 |
DelaunayClarkson represents an O(N*logN) method
|
47 |
with high overhead to find the Delaunay triangulation
|
48 |
of a set of samples of R^DomainDimension.<P>
|
49 |
*/
|
50 |
public class DelaunayClarkson extends Delaunay { |
51 |
|
52 |
/* ******* BEGINNING OF CONVERTED HULL CODE ******* */
|
53 |
|
54 |
// <<<< Constants >>>>
|
55 |
private static final double DBL_MANT_DIG = 53; |
56 |
private static final double FLT_RADIX = 2; |
57 |
private static final double DBL_EPSILON = 2.2204460492503131E-16; |
58 |
private static final double ln2 = Math.log(2); |
59 |
|
60 |
|
61 |
// <<<< Variables >>>>
|
62 |
/* we need to have two indices for every pointer into basis_s and
|
63 |
simplex arrays, because they are two-dimensional arrays of
|
64 |
blocks. ( _bn = block number ) */
|
65 |
|
66 |
// for the pseudo-pointers
|
67 |
private static final int INFINITY = -2; // replaces infinity |
68 |
private static final int NOVAL = -1; // replaces null |
69 |
|
70 |
private double[][] site_blocks; // copy of samples array |
71 |
private int[][] a3s; // output array |
72 |
private int a3size; // output array maximum size |
73 |
private int nts = 0; // # output objects |
74 |
|
75 |
private static final int max_blocks = 10000; // max # basis/simplex blocks |
76 |
private static final int Nobj = 10000; |
77 |
private static final int MAXDIM = 8; // max dimension |
78 |
|
79 |
private int dim; |
80 |
private int p; |
81 |
private long pnum; |
82 |
private int rdim, // region dimension |
83 |
cdim; // # sites currently specifying region
|
84 |
private int exact_bits; |
85 |
private double b_err_min, |
86 |
b_err_min_sq; |
87 |
private double ldetbound = 0; |
88 |
private int failcount = 0; // static: reduce_inner |
89 |
private int lscale; // static: reduce_inner |
90 |
private double max_scale; // static: reduce_inner |
91 |
private float Sb; // static: reduce_inner |
92 |
private int nsb = 0; // # simplex blocks |
93 |
private int nbb = 0; // # basis_s blocks |
94 |
private int ss = MAXDIM; // static: search |
95 |
private int ss2 = 2000; // static: visit_triang |
96 |
private long vnum = -1; // static: visit_triang |
97 |
private int p_neigh_vert = NOVAL; // static: main |
98 |
|
99 |
// "void stuff" -- dummy variables to hold unused return information
|
100 |
private int[] voidp = new int[1]; |
101 |
private int[] voidp_bn = new int[1]; |
102 |
|
103 |
// basis_s stuff
|
104 |
private int[][] bbt_next = new int[max_blocks][]; |
105 |
private int[][] bbt_next_bn = new int[max_blocks][]; |
106 |
private int[][] bbt_ref_count = new int[max_blocks][]; |
107 |
private int[][] bbt_lscale = new int[max_blocks][]; |
108 |
private double[][] bbt_sqa = new double[max_blocks][]; |
109 |
private double[][] bbt_sqb = new double[max_blocks][]; |
110 |
private double[][][] bbt_vecs = new double[max_blocks][][]; |
111 |
|
112 |
private int ttbp; |
113 |
private int ttbp_bn; |
114 |
private int ib; |
115 |
private int ib_bn; |
116 |
private int basis_s_list = NOVAL; |
117 |
private int basis_s_list_bn; |
118 |
private int pnb = NOVAL; |
119 |
private int pnb_bn; |
120 |
private int b = NOVAL; // static: sees |
121 |
private int b_bn; |
122 |
|
123 |
// simplex stuff
|
124 |
private int[][] sbt_next = new int[max_blocks][]; |
125 |
private int[][] sbt_next_bn = new int[max_blocks][]; |
126 |
private long[][] sbt_visit = new long[max_blocks][]; |
127 |
private short[][] sbt_mark = new short[max_blocks][]; |
128 |
private int[][] sbt_normal = new int[max_blocks][]; |
129 |
private int[][] sbt_normal_bn = new int[max_blocks][]; |
130 |
private int[][] sbt_peak_vert = new int[max_blocks][]; |
131 |
private int[][] sbt_peak_simp = new int[max_blocks][]; |
132 |
private int[][] sbt_peak_simp_bn = new int[max_blocks][]; |
133 |
private int[][] sbt_peak_basis = new int[max_blocks][]; |
134 |
private int[][] sbt_peak_basis_bn = new int[max_blocks][]; |
135 |
private int[][][] sbt_neigh_vert = new int[max_blocks][][]; |
136 |
private int[][][] sbt_neigh_simp = new int[max_blocks][][]; |
137 |
private int[][][] sbt_neigh_simp_bn = new int[max_blocks][][]; |
138 |
private int[][][] sbt_neigh_basis = new int[max_blocks][][]; |
139 |
private int[][][] sbt_neigh_basis_bn = new int[max_blocks][][]; |
140 |
|
141 |
private int simplex_list = NOVAL; |
142 |
private int simplex_list_bn; |
143 |
private int ch_root; |
144 |
private int ch_root_bn; |
145 |
private int ns; // static: make_facets |
146 |
private int ns_bn; |
147 |
private int[] st = new int[ss+MAXDIM+1]; // static: search |
148 |
private int[] st_bn = new int[ss+MAXDIM+1]; |
149 |
private int[] st2 = new int[ss2+MAXDIM+1]; // static: visit_triang |
150 |
private int[] st2_bn = new int[ss2+MAXDIM+1]; |
151 |
|
152 |
|
153 |
// <<<< Functions >>>>
|
154 |
private int new_block_basis_s() { |
155 |
bbt_next[nbb] = new int[Nobj]; |
156 |
bbt_next_bn[nbb] = new int[Nobj]; |
157 |
bbt_ref_count[nbb] = new int[Nobj]; |
158 |
bbt_lscale[nbb] = new int[Nobj]; |
159 |
bbt_sqa[nbb] = new double[Nobj]; |
160 |
bbt_sqb[nbb] = new double[Nobj]; |
161 |
bbt_vecs[nbb] = new double[2*rdim][]; |
162 |
for (int i=0; i<2*rdim; i++) bbt_vecs[nbb][i] = new double[Nobj]; |
163 |
for (int i=0; i<Nobj; i++) { |
164 |
bbt_next[nbb][i] = i+1;
|
165 |
bbt_next_bn[nbb][i] = nbb; |
166 |
bbt_ref_count[nbb][i] = 0;
|
167 |
bbt_lscale[nbb][i] = 0;
|
168 |
bbt_sqa[nbb][i] = 0;
|
169 |
bbt_sqb[nbb][i] = 0;
|
170 |
for (int j=0; j<2*rdim; j++) bbt_vecs[nbb][j][i] = 0; |
171 |
} |
172 |
bbt_next[nbb][Nobj-1] = NOVAL;
|
173 |
basis_s_list = 0;
|
174 |
basis_s_list_bn = nbb; |
175 |
nbb++; |
176 |
return basis_s_list;
|
177 |
} |
178 |
|
179 |
private int reduce_inner(int v, int v_bn, int s, int s_bn, int k) { |
180 |
int q, q_bn;
|
181 |
double dd,
|
182 |
Sb = 0;
|
183 |
double scale;
|
184 |
|
185 |
bbt_sqa[v_bn][v] = 0;
|
186 |
for (int i=0; i<rdim; i++) { |
187 |
bbt_sqa[v_bn][v] += bbt_vecs[v_bn][i][v] * bbt_vecs[v_bn][i][v]; |
188 |
} |
189 |
bbt_sqb[v_bn][v] = bbt_sqa[v_bn][v]; |
190 |
if (k <= 1) { |
191 |
for (int i=0; i<rdim; i++) { |
192 |
bbt_vecs[v_bn][i][v] = bbt_vecs[v_bn][rdim+i][v]; |
193 |
} |
194 |
return 1; |
195 |
} |
196 |
for (int j=0; j<250; j++) { |
197 |
int xx = rdim;
|
198 |
double labound;
|
199 |
|
200 |
for (int i=0; i<rdim; i++) { |
201 |
bbt_vecs[v_bn][i][v] = bbt_vecs[v_bn][rdim+i][v]; |
202 |
} |
203 |
for (int i=k-1; i>0; i--) { |
204 |
q = sbt_neigh_basis[s_bn][i][s]; |
205 |
q_bn = sbt_neigh_basis_bn[s_bn][i][s]; |
206 |
dd = 0;
|
207 |
for (int l=0; l<rdim; l++) { |
208 |
dd -= bbt_vecs[q_bn][l][q] * bbt_vecs[v_bn][l][v]; |
209 |
} |
210 |
dd /= bbt_sqb[q_bn][q]; |
211 |
for (int l=0; l<rdim; l++) { |
212 |
bbt_vecs[v_bn][l][v] += dd * bbt_vecs[q_bn][rdim+l][q]; |
213 |
} |
214 |
} |
215 |
bbt_sqb[v_bn][v] = 0;
|
216 |
for (int i=0; i<rdim; i++) { |
217 |
bbt_sqb[v_bn][v] += bbt_vecs[v_bn][i][v] * bbt_vecs[v_bn][i][v]; |
218 |
} |
219 |
bbt_sqa[v_bn][v] = 0;
|
220 |
for (int i=0; i<rdim; i++) { |
221 |
bbt_sqa[v_bn][v] += bbt_vecs[v_bn][rdim+i][v] |
222 |
* bbt_vecs[v_bn][rdim+i][v]; |
223 |
} |
224 |
|
225 |
if (2*bbt_sqb[v_bn][v] >= bbt_sqa[v_bn][v]) return 1; |
226 |
|
227 |
// scale up vector
|
228 |
if (j < 10) { |
229 |
labound = Math.floor(Math.log(bbt_sqa[v_bn][v])/ln2) / 2; |
230 |
max_scale = exact_bits-labound-0.66*(k-2)-1; |
231 |
if (max_scale < 1) max_scale = 1; |
232 |
|
233 |
if (j == 0) { |
234 |
|
235 |
ldetbound = 0;
|
236 |
Sb = 0;
|
237 |
for (int l=k-1; l>0; l--) { |
238 |
q = sbt_neigh_basis[s_bn][l][s]; |
239 |
q_bn = sbt_neigh_basis_bn[s_bn][l][s]; |
240 |
Sb += bbt_sqb[q_bn][q]; |
241 |
ldetbound += Math.floor(Math.log(bbt_sqb[q_bn][q])/ln2) / 2 + 1; |
242 |
ldetbound -= bbt_lscale[q_bn][q]; |
243 |
} |
244 |
} |
245 |
} |
246 |
if (ldetbound - bbt_lscale[v_bn][v]
|
247 |
+ Math.floor(Math.log(bbt_sqb[v_bn][v])/ln2) / 2 + 1 < 0) { |
248 |
scale = 0;
|
249 |
} |
250 |
else {
|
251 |
lscale = (int) (Math.log(2*Sb/(bbt_sqb[v_bn][v] |
252 |
+ bbt_sqa[v_bn][v]*b_err_min))/ln2) / 2;
|
253 |
if (lscale > max_scale) lscale = (int) max_scale; |
254 |
else if (lscale < 0) lscale = 0; |
255 |
bbt_lscale[v_bn][v] += lscale; |
256 |
scale = (lscale < 20) ? 1 << lscale : Math.pow(2, lscale); |
257 |
} |
258 |
|
259 |
while (xx < 2*rdim) bbt_vecs[v_bn][xx++][v] *= scale; |
260 |
|
261 |
for (int i=k-1; i>0; i--) { |
262 |
q = sbt_neigh_basis[s_bn][i][s]; |
263 |
q_bn = sbt_neigh_basis_bn[s_bn][i][s]; |
264 |
dd = 0;
|
265 |
for (int l=0; l<rdim; l++) { |
266 |
dd -= bbt_vecs[q_bn][l][q] * bbt_vecs[v_bn][rdim+l][v]; |
267 |
} |
268 |
dd /= bbt_sqb[q_bn][q]; |
269 |
dd = Math.floor(dd+0.5); |
270 |
for (int l=0; l<rdim; l++) { |
271 |
bbt_vecs[v_bn][rdim+l][v] += dd * bbt_vecs[q_bn][rdim+l][q]; |
272 |
} |
273 |
} |
274 |
} |
275 |
if (failcount++ < 10) System.out.println("reduce_inner failed!"); |
276 |
return 0; |
277 |
} |
278 |
|
279 |
private int reduce(int[] v, int[] v_bn, int rp, int s, int s_bn, int k) { |
280 |
if (v[0] == NOVAL) { |
281 |
v[0] = basis_s_list != NOVAL ? basis_s_list : new_block_basis_s();
|
282 |
v_bn[0] = basis_s_list_bn;
|
283 |
basis_s_list = bbt_next[v_bn[0]][v[0]]; |
284 |
basis_s_list_bn = bbt_next_bn[v_bn[0]][v[0]]; |
285 |
bbt_ref_count[v_bn[0]][v[0]] = 1; |
286 |
} |
287 |
else bbt_lscale[v_bn[0]][v[0]] = 0; |
288 |
if (rp == INFINITY) {
|
289 |
bbt_next[v_bn[0]][v[0]] = bbt_next[ib_bn][ib]; |
290 |
bbt_next_bn[v_bn[0]][v[0]] = bbt_next_bn[ib_bn][ib]; |
291 |
bbt_ref_count[v_bn[0]][v[0]] = bbt_ref_count[ib_bn][ib]; |
292 |
bbt_lscale[v_bn[0]][v[0]] = bbt_lscale[ib_bn][ib]; |
293 |
bbt_sqa[v_bn[0]][v[0]] = bbt_sqa[ib_bn][ib]; |
294 |
bbt_sqb[v_bn[0]][v[0]] = bbt_sqb[ib_bn][ib]; |
295 |
for (int i=0; i<2*rdim; i++) { |
296 |
bbt_vecs[v_bn[0]][i][v[0]] = bbt_vecs[ib_bn][i][ib]; |
297 |
} |
298 |
} |
299 |
else {
|
300 |
double sum = 0; |
301 |
int sbt_nv = sbt_neigh_vert[s_bn][0][s]; |
302 |
if (sbt_nv == INFINITY) {
|
303 |
for (int i=0; i<dim; i++) { |
304 |
bbt_vecs[v_bn[0]][i+rdim][v[0]] = bbt_vecs[v_bn[0]][i][v[0]] |
305 |
= (double) site_blocks[i][rp];
|
306 |
} |
307 |
} |
308 |
else {
|
309 |
for (int i=0; i<dim; i++) { |
310 |
bbt_vecs[v_bn[0]][i+rdim][v[0]] = bbt_vecs[v_bn[0]][i][v[0]] |
311 |
= (double) (site_blocks[i][rp] - site_blocks[i][sbt_nv]);
|
312 |
} |
313 |
} |
314 |
for (int i=0; i<dim; i++) { |
315 |
sum += bbt_vecs[v_bn[0]][i][v[0]] * bbt_vecs[v_bn[0]][i][v[0]]; |
316 |
} |
317 |
bbt_vecs[v_bn[0]][2*rdim-1][v[0]] = sum; |
318 |
bbt_vecs[v_bn[0]][rdim-1][v[0]] = sum; |
319 |
} |
320 |
return reduce_inner(v[0], v_bn[0], s, s_bn, k); |
321 |
} |
322 |
|
323 |
private void get_basis_sede(int s, int s_bn) { |
324 |
int k=1; |
325 |
int q, q_bn;
|
326 |
int[] curt = new int[1]; |
327 |
int[] curt_bn = new int[1]; |
328 |
|
329 |
if (sbt_neigh_vert[s_bn][0][s] == INFINITY && cdim > 1) { |
330 |
int t_vert, t_simp, t_simp_bn, t_basis, t_basis_bn;
|
331 |
t_vert = sbt_neigh_vert[s_bn][0][s];
|
332 |
t_simp = sbt_neigh_simp[s_bn][0][s];
|
333 |
t_simp_bn = sbt_neigh_simp_bn[s_bn][0][s];
|
334 |
t_basis = sbt_neigh_basis[s_bn][0][s];
|
335 |
t_basis_bn = sbt_neigh_basis_bn[s_bn][0][s];
|
336 |
sbt_neigh_vert[s_bn][0][s] = sbt_neigh_vert[s_bn][k][s];
|
337 |
sbt_neigh_simp[s_bn][0][s] = sbt_neigh_simp[s_bn][k][s];
|
338 |
sbt_neigh_simp_bn[s_bn][0][s] = sbt_neigh_simp_bn[s_bn][k][s];
|
339 |
sbt_neigh_basis[s_bn][0][s] = sbt_neigh_basis[s_bn][k][s];
|
340 |
sbt_neigh_basis_bn[s_bn][0][s] = sbt_neigh_basis_bn[s_bn][k][s];
|
341 |
sbt_neigh_vert[s_bn][k][s] = t_vert; |
342 |
sbt_neigh_simp[s_bn][k][s] = t_simp; |
343 |
sbt_neigh_simp_bn[s_bn][k][s] = t_simp_bn; |
344 |
sbt_neigh_basis[s_bn][k][s] = t_basis; |
345 |
sbt_neigh_basis_bn[s_bn][k][s] = t_basis_bn; |
346 |
|
347 |
q = sbt_neigh_basis[s_bn][0][s];
|
348 |
q_bn = sbt_neigh_basis_bn[s_bn][0][s];
|
349 |
if ((q != NOVAL) && --bbt_ref_count[q_bn][q] == 0) { |
350 |
bbt_next[q_bn][q] = basis_s_list; |
351 |
bbt_next_bn[q_bn][q] = basis_s_list_bn; |
352 |
bbt_ref_count[q_bn][q] = 0;
|
353 |
bbt_lscale[q_bn][q] = 0;
|
354 |
bbt_sqa[q_bn][q] = 0;
|
355 |
bbt_sqb[q_bn][q] = 0;
|
356 |
for (int j=0; j<2*rdim; j++) bbt_vecs[q_bn][j][q] = 0; |
357 |
basis_s_list = q; |
358 |
basis_s_list_bn = q_bn; |
359 |
} |
360 |
|
361 |
sbt_neigh_basis[s_bn][0][s] = ttbp;
|
362 |
sbt_neigh_basis_bn[s_bn][0][s] = ttbp_bn;
|
363 |
bbt_ref_count[ttbp_bn][ttbp]++; |
364 |
} |
365 |
else {
|
366 |
if (sbt_neigh_basis[s_bn][0][s] == NOVAL) { |
367 |
sbt_neigh_basis[s_bn][0][s] = ttbp;
|
368 |
sbt_neigh_basis_bn[s_bn][0][s] = ttbp_bn;
|
369 |
bbt_ref_count[ttbp_bn][ttbp]++; |
370 |
} else while (k < cdim && sbt_neigh_basis[s_bn][k][s] != NOVAL) k++; |
371 |
} |
372 |
while (k < cdim) {
|
373 |
q = sbt_neigh_basis[s_bn][k][s]; |
374 |
q_bn = sbt_neigh_basis_bn[s_bn][k][s]; |
375 |
if (q != NOVAL && --bbt_ref_count[q_bn][q] == 0) { |
376 |
bbt_next[q_bn][q] = basis_s_list; |
377 |
bbt_next_bn[q_bn][q] = basis_s_list_bn; |
378 |
bbt_ref_count[q_bn][q] = 0;
|
379 |
bbt_lscale[q_bn][q] = 0;
|
380 |
bbt_sqa[q_bn][q] = 0;
|
381 |
bbt_sqb[q_bn][q] = 0;
|
382 |
for (int j=0; j<2*rdim; j++) bbt_vecs[q_bn][j][q] = 0; |
383 |
basis_s_list = q; |
384 |
basis_s_list_bn = q_bn; |
385 |
} |
386 |
sbt_neigh_basis[s_bn][k][s] = NOVAL; |
387 |
curt[0] = sbt_neigh_basis[s_bn][k][s];
|
388 |
curt_bn[0] = sbt_neigh_basis_bn[s_bn][k][s];
|
389 |
reduce(curt, curt_bn, sbt_neigh_vert[s_bn][k][s], s, s_bn, k); |
390 |
sbt_neigh_basis[s_bn][k][s] = curt[0];
|
391 |
sbt_neigh_basis_bn[s_bn][k][s] = curt_bn[0];
|
392 |
k++; |
393 |
} |
394 |
} |
395 |
|
396 |
private int sees(int rp, int s, int s_bn) { |
397 |
double dd, dds;
|
398 |
int q, q_bn, q1, q1_bn, q2, q2_bn;
|
399 |
int[] curt = new int[1]; |
400 |
int[] curt_bn = new int[1]; |
401 |
|
402 |
if (b == NOVAL) {
|
403 |
b = (basis_s_list != NOVAL) ? basis_s_list : new_block_basis_s(); |
404 |
b_bn = basis_s_list_bn; |
405 |
basis_s_list = bbt_next[b_bn][b]; |
406 |
basis_s_list_bn = bbt_next_bn[b_bn][b]; |
407 |
} |
408 |
else bbt_lscale[b_bn][b] = 0; |
409 |
if (cdim==0) return 0; |
410 |
if (sbt_normal[s_bn][s] == NOVAL) {
|
411 |
get_basis_sede(s, s_bn); |
412 |
if (rdim==3 && cdim==3) { |
413 |
sbt_normal[s_bn][s] = basis_s_list != NOVAL ? basis_s_list |
414 |
: new_block_basis_s(); |
415 |
sbt_normal_bn[s_bn][s] = basis_s_list_bn; |
416 |
q = sbt_normal[s_bn][s]; |
417 |
q_bn = sbt_normal_bn[s_bn][s]; |
418 |
basis_s_list = bbt_next[q_bn][q]; |
419 |
basis_s_list_bn = bbt_next_bn[q_bn][q]; |
420 |
q1 = sbt_neigh_basis[s_bn][1][s];
|
421 |
q1_bn = sbt_neigh_basis_bn[s_bn][1][s];
|
422 |
q2 = sbt_neigh_basis[s_bn][2][s];
|
423 |
q2_bn = sbt_neigh_basis_bn[s_bn][2][s];
|
424 |
bbt_ref_count[q_bn][q] = 1;
|
425 |
bbt_vecs[q_bn][0][q] = bbt_vecs[q1_bn][1][q1] |
426 |
*bbt_vecs[q2_bn][2][q2]
|
427 |
- bbt_vecs[q1_bn][2][q1]
|
428 |
*bbt_vecs[q2_bn][1][q2];
|
429 |
bbt_vecs[q_bn][1][q] = bbt_vecs[q1_bn][2][q1] |
430 |
*bbt_vecs[q2_bn][0][q2]
|
431 |
- bbt_vecs[q1_bn][0][q1]
|
432 |
*bbt_vecs[q2_bn][2][q2];
|
433 |
bbt_vecs[q_bn][2][q] = bbt_vecs[q1_bn][0][q1] |
434 |
*bbt_vecs[q2_bn][1][q2]
|
435 |
- bbt_vecs[q1_bn][1][q1]
|
436 |
*bbt_vecs[q2_bn][0][q2];
|
437 |
bbt_sqb[q_bn][q] = 0;
|
438 |
for (int i=0; i<rdim; i++) bbt_sqb[q_bn][q] += bbt_vecs[q_bn][i][q] |
439 |
* bbt_vecs[q_bn][i][q]; |
440 |
for (int i=cdim+1; i>0; i--) { |
441 |
int m = (i > 1) ? sbt_neigh_vert[ch_root_bn][i-2][ch_root] |
442 |
: INFINITY; |
443 |
int j;
|
444 |
for (j=0; j<cdim && m != sbt_neigh_vert[s_bn][j][s]; j++); |
445 |
if (j < cdim) continue; |
446 |
if (m == INFINITY) {
|
447 |
if (bbt_vecs[q_bn][2][q] > -b_err_min) continue; |
448 |
} |
449 |
else {
|
450 |
if (sees(m, s, s_bn) == 0) { |
451 |
continue;
|
452 |
} |
453 |
} |
454 |
bbt_vecs[q_bn][0][q] = -bbt_vecs[q_bn][0][q]; |
455 |
bbt_vecs[q_bn][1][q] = -bbt_vecs[q_bn][1][q]; |
456 |
bbt_vecs[q_bn][2][q] = -bbt_vecs[q_bn][2][q]; |
457 |
break;
|
458 |
} |
459 |
} |
460 |
else {
|
461 |
for (int i=cdim+1; i>0; i--) { |
462 |
int m = (i > 1) ? sbt_neigh_vert[ch_root_bn][i-2][ch_root] |
463 |
: INFINITY; |
464 |
int j;
|
465 |
for (j=0; j<cdim && m != sbt_neigh_vert[s_bn][j][s]; j++); |
466 |
if (j < cdim) continue; |
467 |
curt[0] = sbt_normal[s_bn][s];
|
468 |
curt_bn[0] = sbt_normal_bn[s_bn][s];
|
469 |
reduce(curt, curt_bn, m, s, s_bn, cdim); |
470 |
q = sbt_normal[s_bn][s] = curt[0];
|
471 |
q_bn = sbt_normal_bn[s_bn][s] = curt_bn[0];
|
472 |
if (bbt_sqb[q_bn][q] != 0) break; |
473 |
} |
474 |
} |
475 |
|
476 |
for (int i=0; i<cdim; i++) { |
477 |
q = sbt_neigh_basis[s_bn][i][s]; |
478 |
q_bn = sbt_neigh_basis_bn[s_bn][i][s]; |
479 |
if (q != NOVAL && --bbt_ref_count[q_bn][q] == 0) { |
480 |
bbt_next[q_bn][q] = basis_s_list; |
481 |
bbt_next_bn[q_bn][q] = basis_s_list_bn; |
482 |
bbt_ref_count[q_bn][q] = 0;
|
483 |
bbt_lscale[q_bn][q] = 0;
|
484 |
bbt_sqa[q_bn][q] = 0;
|
485 |
bbt_sqb[q_bn][q] = 0;
|
486 |
for (int l=0; l<2*rdim; l++) bbt_vecs[q_bn][l][q] = 0; |
487 |
basis_s_list = q; |
488 |
basis_s_list_bn = q_bn; |
489 |
} |
490 |
sbt_neigh_basis[s_bn][i][s] = NOVAL; |
491 |
} |
492 |
} |
493 |
if (rp == INFINITY) {
|
494 |
bbt_next[b_bn][b] = bbt_next[ib_bn][ib]; |
495 |
bbt_next_bn[b_bn][b] = bbt_next_bn[ib_bn][ib]; |
496 |
bbt_ref_count[b_bn][b] = bbt_ref_count[ib_bn][ib]; |
497 |
bbt_lscale[b_bn][b] = bbt_lscale[ib_bn][ib]; |
498 |
bbt_sqa[b_bn][b] = bbt_sqa[ib_bn][ib]; |
499 |
bbt_sqb[b_bn][b] = bbt_sqb[ib_bn][ib]; |
500 |
for (int i=0; i<2*rdim; i++) { |
501 |
bbt_vecs[b_bn][i][b] = bbt_vecs[ib_bn][i][ib]; |
502 |
} |
503 |
} |
504 |
else {
|
505 |
double sum = 0; |
506 |
int sbt_nv = sbt_neigh_vert[s_bn][0][s]; |
507 |
if (sbt_nv == INFINITY) {
|
508 |
for (int l=0; l<dim; l++) { |
509 |
bbt_vecs[b_bn][l+rdim][b] = bbt_vecs[b_bn][l][b] |
510 |
= (double) site_blocks[l][rp];
|
511 |
} |
512 |
} |
513 |
else {
|
514 |
for (int l=0; l<dim; l++) { |
515 |
bbt_vecs[b_bn][l+rdim][b] = bbt_vecs[b_bn][l][b] |
516 |
= (double) (site_blocks[l][rp] - site_blocks[l][sbt_nv]);
|
517 |
} |
518 |
} |
519 |
for (int l=0; l<dim; l++) { |
520 |
sum += bbt_vecs[b_bn][l][b] * bbt_vecs[b_bn][l][b]; |
521 |
} |
522 |
bbt_vecs[b_bn][2*rdim-1][b] = bbt_vecs[b_bn][rdim-1][b] = sum; |
523 |
} |
524 |
q = sbt_normal[s_bn][s]; |
525 |
q_bn = sbt_normal_bn[s_bn][s]; |
526 |
for (int i=0; i<3; i++) { |
527 |
double sum = 0; |
528 |
dd = 0;
|
529 |
for (int l=0; l<rdim; l++) { |
530 |
dd += bbt_vecs[b_bn][l][b] * bbt_vecs[q_bn][l][q]; |
531 |
} |
532 |
if (dd == 0.0) return 0; |
533 |
for (int l=0; l<rdim; l++) { |
534 |
sum += bbt_vecs[b_bn][l][b] * bbt_vecs[b_bn][l][b]; |
535 |
} |
536 |
dds = dd*dd/bbt_sqb[q_bn][q]/sum; |
537 |
if (dds > b_err_min_sq) return (dd < 0 ? 1 : 0); |
538 |
get_basis_sede(s, s_bn); |
539 |
reduce_inner(b, b_bn, s, s_bn, cdim); |
540 |
} |
541 |
return 0; |
542 |
} |
543 |
|
544 |
private int new_block_simplex() { |
545 |
sbt_next[nsb] = new int[Nobj]; |
546 |
sbt_next_bn[nsb] = new int[Nobj]; |
547 |
sbt_visit[nsb] = new long[Nobj]; |
548 |
sbt_mark[nsb] = new short[Nobj]; |
549 |
sbt_normal[nsb] = new int[Nobj]; |
550 |
sbt_normal_bn[nsb] = new int[Nobj]; |
551 |
sbt_peak_vert[nsb] = new int[Nobj]; |
552 |
sbt_peak_simp[nsb] = new int[Nobj]; |
553 |
sbt_peak_simp_bn[nsb] = new int[Nobj]; |
554 |
sbt_peak_basis[nsb] = new int[Nobj]; |
555 |
sbt_peak_basis_bn[nsb] = new int[Nobj]; |
556 |
sbt_neigh_vert[nsb] = new int[rdim][]; |
557 |
sbt_neigh_simp[nsb] = new int[rdim][]; |
558 |
sbt_neigh_simp_bn[nsb] = new int[rdim][]; |
559 |
sbt_neigh_basis[nsb] = new int[rdim][]; |
560 |
sbt_neigh_basis_bn[nsb] = new int[rdim][]; |
561 |
for (int i=0; i<rdim; i++) { |
562 |
sbt_neigh_vert[nsb][i] = new int[Nobj]; |
563 |
sbt_neigh_simp[nsb][i] = new int[Nobj]; |
564 |
sbt_neigh_simp_bn[nsb][i] = new int[Nobj]; |
565 |
sbt_neigh_basis[nsb][i] = new int[Nobj]; |
566 |
sbt_neigh_basis_bn[nsb][i] = new int[Nobj]; |
567 |
} |
568 |
for (int i=0; i<Nobj; i++) { |
569 |
sbt_next[nsb][i] = i+1;
|
570 |
sbt_next_bn[nsb][i] = nsb; |
571 |
sbt_visit[nsb][i] = 0;
|
572 |
sbt_mark[nsb][i] = 0;
|
573 |
sbt_normal[nsb][i] = NOVAL; |
574 |
sbt_peak_vert[nsb][i] = NOVAL; |
575 |
sbt_peak_simp[nsb][i] = NOVAL; |
576 |
sbt_peak_basis[nsb][i] = NOVAL; |
577 |
for (int j=0; j<rdim; j++) { |
578 |
sbt_neigh_vert[nsb][j][i] = NOVAL; |
579 |
sbt_neigh_simp[nsb][j][i] = NOVAL; |
580 |
sbt_neigh_basis[nsb][j][i] = NOVAL; |
581 |
} |
582 |
} |
583 |
sbt_next[nsb][Nobj-1] = NOVAL;
|
584 |
simplex_list = 0;
|
585 |
simplex_list_bn = nsb; |
586 |
|
587 |
nsb++; |
588 |
return simplex_list;
|
589 |
} |
590 |
|
591 |
/**
|
592 |
starting at s, visit simplices t such that test(s,i,0) is true,
|
593 |
and t is the i'th neighbor of s;
|
594 |
apply visit function to all visited simplices;
|
595 |
when visit returns nonnull, exit and return its value.
|
596 |
*/
|
597 |
private void visit_triang_gen(int s, int s_bn, int whichfunc, |
598 |
int[] ret, int[] ret_bn) { |
599 |
int v;
|
600 |
int v_bn;
|
601 |
int t;
|
602 |
int t_bn;
|
603 |
int tms = 0; |
604 |
|
605 |
vnum--; |
606 |
if (s != NOVAL) {
|
607 |
st2[tms] = s; |
608 |
st2_bn[tms] = s_bn; |
609 |
tms++; |
610 |
} |
611 |
while (tms != 0) { |
612 |
if (tms > ss2) {
|
613 |
// JAVA: efficiency issue: how much is this stack hammered?
|
614 |
ss2 += ss2; |
615 |
int[] newst2 = new int[ss2+MAXDIM+1]; |
616 |
int[] newst2_bn = new int[ss2+MAXDIM+1]; |
617 |
System.arraycopy(st2, 0, newst2, 0, st2.length); |
618 |
System.arraycopy(st2_bn, 0, newst2_bn, 0, st2_bn.length); |
619 |
st2 = newst2; |
620 |
st2_bn = newst2_bn; |
621 |
} |
622 |
tms--; |
623 |
t = st2[tms]; |
624 |
t_bn = st2_bn[tms]; |
625 |
if (t == NOVAL || sbt_visit[t_bn][t] == vnum) continue; |
626 |
sbt_visit[t_bn][t] = vnum; |
627 |
if (whichfunc == 1) { |
628 |
if (sbt_peak_vert[t_bn][t] == NOVAL) {
|
629 |
v = t; |
630 |
v_bn = t_bn; |
631 |
} |
632 |
else {
|
633 |
v = NOVAL; |
634 |
v_bn = NOVAL; |
635 |
} |
636 |
if (v != NOVAL) {
|
637 |
ret[0] = v;
|
638 |
ret_bn[0] = v_bn;
|
639 |
return;
|
640 |
} |
641 |
} |
642 |
else {
|
643 |
int[] vfp = new int[cdim]; |
644 |
|
645 |
if (t != NOVAL) {
|
646 |
for (int j=0; j<cdim; j++) vfp[j] = sbt_neigh_vert[t_bn][j][t]; |
647 |
for (int j=0; j<cdim; j++) { |
648 |
a3s[j][nts] = (vfp[j] == INFINITY) ? -1 : vfp[j];
|
649 |
} |
650 |
nts++; |
651 |
if (nts > a3size) {
|
652 |
// JAVA: efficiency issue, hammering an array
|
653 |
a3size += a3size; |
654 |
int[][] newa3s = new int[rdim][a3size+MAXDIM+1]; |
655 |
for (int i=0; i<rdim; i++) { |
656 |
System.arraycopy(a3s[i], 0, newa3s[i], 0, a3s[i].length); |
657 |
} |
658 |
a3s = newa3s; |
659 |
} |
660 |
} |
661 |
} |
662 |
for (int i=0; i<cdim; i++) { |
663 |
int j = sbt_neigh_simp[t_bn][i][t];
|
664 |
int j_bn = sbt_neigh_simp_bn[t_bn][i][t];
|
665 |
if ((j != NOVAL) && sbt_visit[j_bn][j] != vnum) {
|
666 |
st2[tms] = j; |
667 |
st2_bn[tms] = j_bn; |
668 |
tms++; |
669 |
} |
670 |
} |
671 |
} |
672 |
ret[0] = NOVAL;
|
673 |
} |
674 |
|
675 |
/**
|
676 |
make neighbor connections between newly created simplices incident to p.
|
677 |
*/
|
678 |
private void connect(int s, int s_bn) { |
679 |
int xb, xf;
|
680 |
int sb, sb_bn;
|
681 |
int sf, sf_bn;
|
682 |
int tf, tf_bn;
|
683 |
int ccj, ccj_bn;
|
684 |
int xfi;
|
685 |
|
686 |
if (s == NOVAL) return; |
687 |
for (int i=0; (sbt_neigh_vert[s_bn][i][s] != p) && (i<cdim); i++); |
688 |
if (sbt_visit[s_bn][s] == pnum) return; |
689 |
sbt_visit[s_bn][s] = pnum; |
690 |
ccj = sbt_peak_simp[s_bn][s]; |
691 |
ccj_bn = sbt_peak_simp_bn[s_bn][s]; |
692 |
for (xfi=0; (sbt_neigh_simp[ccj_bn][xfi][ccj] != s |
693 |
|| sbt_neigh_simp_bn[ccj_bn][xfi][ccj] != s_bn) |
694 |
&& (xfi<cdim); xfi++); |
695 |
for (int i=0; i<cdim; i++) { |
696 |
int l;
|
697 |
if (p == sbt_neigh_vert[s_bn][i][s]) continue; |
698 |
sb = sbt_peak_simp[s_bn][s]; |
699 |
sb_bn = sbt_peak_simp_bn[s_bn][s]; |
700 |
sf = sbt_neigh_simp[s_bn][i][s]; |
701 |
sf_bn = sbt_neigh_simp_bn[s_bn][i][s]; |
702 |
xf = sbt_neigh_vert[ccj_bn][xfi][ccj]; |
703 |
if (sbt_peak_vert[sf_bn][sf] == NOVAL) { // are we done already? |
704 |
for (l=0; (sbt_neigh_vert[ccj_bn][l][ccj] |
705 |
!= sbt_neigh_vert[s_bn][i][s]) && (l<cdim); l++); |
706 |
sf = sbt_neigh_simp[ccj_bn][l][ccj]; |
707 |
sf_bn = sbt_neigh_simp_bn[ccj_bn][l][ccj]; |
708 |
if (sbt_peak_vert[sf_bn][sf] != NOVAL) continue; |
709 |
} else do { |
710 |
xb = xf; |
711 |
for (l=0; (sbt_neigh_simp[sf_bn][l][sf] != sb |
712 |
|| sbt_neigh_simp_bn[sf_bn][l][sf] != sb_bn) |
713 |
&& l<cdim; l++); |
714 |
xf = sbt_neigh_vert[sf_bn][l][sf]; |
715 |
sb = sf; |
716 |
sb_bn = sf_bn; |
717 |
for (l=0; (sbt_neigh_vert[sb_bn][l][sb] != xb) && (l<cdim); l++); |
718 |
tf = sbt_neigh_simp[sf_bn][l][sf]; |
719 |
tf_bn = sbt_neigh_simp_bn[sf_bn][l][sf]; |
720 |
sf = tf; |
721 |
sf_bn = tf_bn; |
722 |
} while (sbt_peak_vert[sf_bn][sf] != NOVAL);
|
723 |
|
724 |
sbt_neigh_simp[s_bn][i][s] = sf; |
725 |
sbt_neigh_simp_bn[s_bn][i][s] = sf_bn; |
726 |
for (l=0; (sbt_neigh_vert[sf_bn][l][sf] != xf) && (l<cdim); l++); |
727 |
sbt_neigh_simp[sf_bn][l][sf] = s; |
728 |
sbt_neigh_simp_bn[sf_bn][l][sf] = s_bn; |
729 |
|
730 |
connect(sf, sf_bn); |
731 |
} |
732 |
|
733 |
} |
734 |
|
735 |
/**
|
736 |
visit simplices s with sees(p,s), and make a facet for every neighbor
|
737 |
of s not seen by p.
|
738 |
*/
|
739 |
private void make_facets(int seen, int seen_bn, int[] ret, int[] ret_bn) { |
740 |
int n, n_bn;
|
741 |
int q, q_bn;
|
742 |
int j;
|
743 |
|
744 |
if (seen == NOVAL) {
|
745 |
ret[0] = NOVAL;
|
746 |
return;
|
747 |
} |
748 |
sbt_peak_vert[seen_bn][seen] = p; |
749 |
|
750 |
for (int i=0; i<cdim; i++) { |
751 |
n = sbt_neigh_simp[seen_bn][i][seen]; |
752 |
n_bn = sbt_neigh_simp_bn[seen_bn][i][seen]; |
753 |
|
754 |
if (pnum != sbt_visit[n_bn][n]) {
|
755 |
sbt_visit[n_bn][n] = pnum; |
756 |
if (sees(p, n, n_bn) != 0) make_facets(n, n_bn, voidp, voidp_bn); |
757 |
} |
758 |
if (sbt_peak_vert[n_bn][n] != NOVAL) continue; |
759 |
|
760 |
ns = (simplex_list != NOVAL) ? simplex_list : new_block_simplex(); |
761 |
ns_bn = simplex_list_bn; |
762 |
simplex_list = sbt_next[ns_bn][ns]; |
763 |
simplex_list_bn = sbt_next_bn[ns_bn][ns]; |
764 |
sbt_next[ns_bn][ns] = sbt_next[seen_bn][seen]; |
765 |
sbt_next_bn[ns_bn][ns] = sbt_next_bn[seen_bn][seen]; |
766 |
sbt_visit[ns_bn][ns] = sbt_visit[seen_bn][seen]; |
767 |
sbt_mark[ns_bn][ns] = sbt_mark[seen_bn][seen]; |
768 |
sbt_normal[ns_bn][ns] = sbt_normal[seen_bn][seen]; |
769 |
sbt_normal_bn[ns_bn][ns] = sbt_normal_bn[seen_bn][seen]; |
770 |
sbt_peak_vert[ns_bn][ns] = sbt_peak_vert[seen_bn][seen]; |
771 |
sbt_peak_simp[ns_bn][ns] = sbt_peak_simp[seen_bn][seen]; |
772 |
sbt_peak_simp_bn[ns_bn][ns] = sbt_peak_simp_bn[seen_bn][seen]; |
773 |
sbt_peak_basis[ns_bn][ns] = sbt_peak_basis[seen_bn][seen]; |
774 |
sbt_peak_basis_bn[ns_bn][ns] = sbt_peak_basis_bn[seen_bn][seen]; |
775 |
for (j=0; j<rdim; j++) { |
776 |
sbt_neigh_vert[ns_bn][j][ns] = sbt_neigh_vert[seen_bn][j][seen]; |
777 |
sbt_neigh_simp[ns_bn][j][ns] = sbt_neigh_simp[seen_bn][j][seen]; |
778 |
sbt_neigh_simp_bn[ns_bn][j][ns] |
779 |
= sbt_neigh_simp_bn[seen_bn][j][seen]; |
780 |
sbt_neigh_basis[ns_bn][j][ns] = sbt_neigh_basis[seen_bn][j][seen]; |
781 |
sbt_neigh_basis_bn[ns_bn][j][ns] |
782 |
= sbt_neigh_basis_bn[seen_bn][j][seen]; |
783 |
} |
784 |
|
785 |
for (j=0; j<cdim; j++) { |
786 |
q = sbt_neigh_basis[seen_bn][j][seen]; |
787 |
q_bn = sbt_neigh_basis_bn[seen_bn][j][seen]; |
788 |
if (q != NOVAL) bbt_ref_count[q_bn][q]++;
|
789 |
} |
790 |
|
791 |
sbt_visit[ns_bn][ns] = 0;
|
792 |
sbt_peak_vert[ns_bn][ns] = NOVAL; |
793 |
sbt_normal[ns_bn][ns] = NOVAL; |
794 |
sbt_peak_simp[ns_bn][ns] = seen; |
795 |
sbt_peak_simp_bn[ns_bn][ns] = seen_bn; |
796 |
|
797 |
q = sbt_neigh_basis[ns_bn][i][ns]; |
798 |
q_bn = sbt_neigh_basis_bn[ns_bn][i][ns]; |
799 |
if (q != NOVAL && --bbt_ref_count[q_bn][q] == 0) { |
800 |
bbt_next[q_bn][q] = basis_s_list; |
801 |
bbt_next_bn[q_bn][q] = basis_s_list_bn; |
802 |
bbt_ref_count[q_bn][q] = 0;
|
803 |
bbt_lscale[q_bn][q] = 0;
|
804 |
bbt_sqa[q_bn][q] = 0;
|
805 |
bbt_sqb[q_bn][q] = 0;
|
806 |
for (int l=0; l<2*rdim; l++) bbt_vecs[q_bn][l][q] = 0; |
807 |
basis_s_list = q; |
808 |
basis_s_list_bn = q_bn; |
809 |
} |
810 |
sbt_neigh_basis[ns_bn][i][ns] = NOVAL; |
811 |
|
812 |
sbt_neigh_vert[ns_bn][i][ns] = p; |
813 |
for (j=0; (sbt_neigh_simp[n_bn][j][n] != seen |
814 |
|| sbt_neigh_simp_bn[n_bn][j][n] != seen_bn) |
815 |
&& j<cdim; j++); |
816 |
sbt_neigh_simp[seen_bn][i][seen] = sbt_neigh_simp[n_bn][j][n] = ns; |
817 |
sbt_neigh_simp_bn[seen_bn][i][seen] = ns_bn; |
818 |
sbt_neigh_simp_bn[n_bn][j][n] = ns_bn; |
819 |
} |
820 |
ret[0] = ns;
|
821 |
ret_bn[0] = ns_bn;
|
822 |
} |
823 |
|
824 |
/**
|
825 |
p lies outside flat containing previous sites;
|
826 |
make p a vertex of every current simplex, and create some new simplices.
|
827 |
*/
|
828 |
private void extend_simplices(int s, int s_bn, int[] ret, int[] ret_bn) { |
829 |
int q, q_bn;
|
830 |
int ns, ns_bn;
|
831 |
|
832 |
if (sbt_visit[s_bn][s] == pnum) {
|
833 |
if (sbt_peak_vert[s_bn][s] != NOVAL) {
|
834 |
ret[0] = sbt_neigh_simp[s_bn][cdim-1][s]; |
835 |
ret_bn[0] = sbt_neigh_simp_bn[s_bn][cdim-1][s]; |
836 |
} |
837 |
else {
|
838 |
ret[0] = s;
|
839 |
ret_bn[0] = s_bn;
|
840 |
} |
841 |
return;
|
842 |
} |
843 |
sbt_visit[s_bn][s] = pnum; |
844 |
sbt_neigh_vert[s_bn][cdim-1][s] = p;
|
845 |
q = sbt_normal[s_bn][s]; |
846 |
q_bn = sbt_normal_bn[s_bn][s]; |
847 |
if (q != NOVAL && --bbt_ref_count[q_bn][q] == 0) { |
848 |
bbt_next[q_bn][q] = basis_s_list; |
849 |
bbt_next_bn[q_bn][q] = basis_s_list_bn; |
850 |
bbt_ref_count[q_bn][q] = 0;
|
851 |
bbt_lscale[q_bn][q] = 0;
|
852 |
bbt_sqa[q_bn][q] = 0;
|
853 |
bbt_sqb[q_bn][q] = 0;
|
854 |
for (int j=0; j<2*rdim; j++) bbt_vecs[q_bn][j][q] = 0; |
855 |
basis_s_list = q; |
856 |
basis_s_list_bn = q_bn; |
857 |
} |
858 |
sbt_normal[s_bn][s] = NOVAL; |
859 |
|
860 |
q = sbt_neigh_basis[s_bn][0][s];
|
861 |
q_bn = sbt_neigh_basis_bn[s_bn][0][s];
|
862 |
if (q != NOVAL && --bbt_ref_count[q_bn][q] == 0) { |
863 |
bbt_next[q_bn][q] = basis_s_list; |
864 |
bbt_ref_count[q_bn][q] = 0;
|
865 |
bbt_lscale[q_bn][q] = 0;
|
866 |
bbt_sqa[q_bn][q] = 0;
|
867 |
bbt_sqb[q_bn][q] = 0;
|
868 |
for (int j=0; j<2*rdim; j++) bbt_vecs[q_bn][j][q] = 0; |
869 |
|
870 |
basis_s_list = q; |
871 |
basis_s_list_bn = q_bn; |
872 |
} |
873 |
sbt_neigh_basis[s_bn][0][s] = NOVAL;
|
874 |
|
875 |
if (sbt_peak_vert[s_bn][s] == NOVAL) {
|
876 |
int[] esretp = new int[1]; |
877 |
int[] esretp_bn = new int[1]; |
878 |
extend_simplices(sbt_peak_simp[s_bn][s], |
879 |
sbt_peak_simp_bn[s_bn][s], esretp, esretp_bn); |
880 |
sbt_neigh_simp[s_bn][cdim-1][s] = esretp[0]; |
881 |
sbt_neigh_simp_bn[s_bn][cdim-1][s] = esretp_bn[0]; |
882 |
ret[0] = s;
|
883 |
ret_bn[0] = s_bn;
|
884 |
return;
|
885 |
} |
886 |
else {
|
887 |
ns = (simplex_list != NOVAL) ? simplex_list : new_block_simplex(); |
888 |
ns_bn = simplex_list_bn; |
889 |
simplex_list = sbt_next[ns_bn][ns]; |
890 |
simplex_list_bn = sbt_next_bn[ns_bn][ns]; |
891 |
sbt_next[ns_bn][ns] = sbt_next[s_bn][s]; |
892 |
sbt_next_bn[ns_bn][ns] = sbt_next_bn[s_bn][s]; |
893 |
sbt_visit[ns_bn][ns] = sbt_visit[s_bn][s]; |
894 |
sbt_mark[ns_bn][ns] = sbt_mark[s_bn][s]; |
895 |
sbt_normal[ns_bn][ns] = sbt_normal[s_bn][s]; |
896 |
sbt_normal_bn[ns_bn][ns] = sbt_normal_bn[s_bn][s]; |
897 |
sbt_peak_vert[ns_bn][ns] = sbt_peak_vert[s_bn][s]; |
898 |
sbt_peak_simp[ns_bn][ns] = sbt_peak_simp[s_bn][s]; |
899 |
sbt_peak_simp_bn[ns_bn][ns] = sbt_peak_simp_bn[s_bn][s]; |
900 |
sbt_peak_basis[ns_bn][ns] = sbt_peak_basis[s_bn][s]; |
901 |
sbt_peak_basis_bn[ns_bn][ns] = sbt_peak_basis_bn[s_bn][s]; |
902 |
for (int j=0; j<rdim; j++) { |
903 |
sbt_neigh_vert[ns_bn][j][ns] = sbt_neigh_vert[s_bn][j][s]; |
904 |
sbt_neigh_simp[ns_bn][j][ns] = sbt_neigh_simp[s_bn][j][s]; |
905 |
sbt_neigh_simp_bn[ns_bn][j][ns] = sbt_neigh_simp_bn[s_bn][j][s]; |
906 |
sbt_neigh_basis[ns_bn][j][ns] = sbt_neigh_basis[s_bn][j][s]; |
907 |
sbt_neigh_basis_bn[ns_bn][j][ns] = sbt_neigh_basis_bn[s_bn][j][s]; |
908 |
} |
909 |
|
910 |
for (int j=0; j<cdim; j++) { |
911 |
q = sbt_neigh_basis[s_bn][j][s]; |
912 |
q_bn = sbt_neigh_basis_bn[s_bn][j][s]; |
913 |
if (q != NOVAL) bbt_ref_count[q_bn][q]++;
|
914 |
} |
915 |
|
916 |
sbt_neigh_simp[s_bn][cdim-1][s] = ns;
|
917 |
sbt_neigh_simp_bn[s_bn][cdim-1][s] = ns_bn;
|
918 |
sbt_peak_vert[ns_bn][ns] = NOVAL; |
919 |
sbt_peak_simp[ns_bn][ns] = s; |
920 |
sbt_peak_simp_bn[ns_bn][ns] = s_bn; |
921 |
sbt_neigh_vert[ns_bn][cdim-1][ns] = sbt_peak_vert[s_bn][s];
|
922 |
sbt_neigh_simp[ns_bn][cdim-1][ns] = sbt_peak_simp[s_bn][s];
|
923 |
sbt_neigh_simp_bn[ns_bn][cdim-1][ns] = sbt_peak_simp_bn[s_bn][s];
|
924 |
sbt_neigh_basis[ns_bn][cdim-1][ns] = sbt_peak_basis[s_bn][s];
|
925 |
sbt_neigh_basis_bn[ns_bn][cdim-1][ns] = sbt_peak_basis_bn[s_bn][s];
|
926 |
q = sbt_peak_basis[s_bn][s]; |
927 |
q_bn = sbt_peak_basis_bn[s_bn][s]; |
928 |
if (q != NOVAL) bbt_ref_count[q_bn][q]++;
|
929 |
for (int i=0; i<cdim; i++) { |
930 |
int[] esretp = new int[1]; |
931 |
int[] esretp_bn = new int[1]; |
932 |
extend_simplices(sbt_neigh_simp[ns_bn][i][ns], |
933 |
sbt_neigh_simp_bn[ns_bn][i][ns], esretp, esretp_bn); |
934 |
sbt_neigh_simp[ns_bn][i][ns] = esretp[0];
|
935 |
sbt_neigh_simp_bn[ns_bn][i][ns] = esretp_bn[0];
|
936 |
} |
937 |
} |
938 |
ret[0] = ns;
|
939 |
ret_bn[0] = ns_bn;
|
940 |
return;
|
941 |
} |
942 |
|
943 |
/**
|
944 |
return a simplex s that corresponds to a facet of the
|
945 |
current hull, and sees(p, s).
|
946 |
*/
|
947 |
private void search(int root, int root_bn, int[] ret, int[] ret_bn) { |
948 |
int s, s_bn;
|
949 |
int tms = 0; |
950 |
|
951 |
st[tms] = sbt_peak_simp[root_bn][root]; |
952 |
st_bn[tms] = sbt_peak_simp_bn[root_bn][root]; |
953 |
tms++; |
954 |
sbt_visit[root_bn][root] = pnum; |
955 |
if (sees(p, root, root_bn) == 0) { |
956 |
for (int i=0; i<cdim; i++) { |
957 |
st[tms] = sbt_neigh_simp[root_bn][i][root]; |
958 |
st_bn[tms] = sbt_neigh_simp_bn[root_bn][i][root]; |
959 |
tms++; |
960 |
} |
961 |
} |
962 |
while (tms != 0) { |
963 |
if (tms > ss) {
|
964 |
// JAVA: efficiency issue: how much is this stack hammered?
|
965 |
ss += ss; |
966 |
int[] newst = new int[ss+MAXDIM+1]; |
967 |
int[] newst_bn = new int[ss+MAXDIM+1]; |
968 |
System.arraycopy(st, 0, newst, 0, st.length); |
969 |
System.arraycopy(st_bn, 0, newst_bn, 0, st_bn.length); |
970 |
st = newst; |
971 |
st_bn = newst_bn; |
972 |
} |
973 |
tms--; |
974 |
s = st[tms]; |
975 |
s_bn = st_bn[tms]; |
976 |
if (sbt_visit[s_bn][s] == pnum) continue; |
977 |
sbt_visit[s_bn][s] = pnum; |
978 |
if (sees(p, s, s_bn) == 0) continue; |
979 |
if (sbt_peak_vert[s_bn][s] == NOVAL) {
|
980 |
ret[0] = s;
|
981 |
ret_bn[0] = s_bn;
|
982 |
return;
|
983 |
} |
984 |
for (int i=0; i<cdim; i++) { |
985 |
st[tms] = sbt_neigh_simp[s_bn][i][s]; |
986 |
st_bn[tms] = sbt_neigh_simp_bn[s_bn][i][s]; |
987 |
tms++; |
988 |
} |
989 |
} |
990 |
ret[0] = NOVAL;
|
991 |
return;
|
992 |
} |
993 |
|
994 |
|
995 |
// <<<< Constructor >>>>
|
996 |
public DelaunayClarkson(double[][] samples) throws VisADException { |
997 |
int s, s_bn, q, q_bn;
|
998 |
int root, root_bn;
|
999 |
int k=0; |
1000 |
int[] retp = new int[1]; |
1001 |
int[] retp_bn = new int[1]; |
1002 |
int[] ret2p = new int[1]; |
1003 |
int[] ret2p_bn = new int[1]; |
1004 |
int[] curt = new int[1]; |
1005 |
int[] curt_bn = new int[1]; |
1006 |
int s_num = 0; |
1007 |
int nrs;
|
1008 |
|
1009 |
// Start of main hull triangulation algorithm
|
1010 |
dim = samples.length; |
1011 |
nrs = samples[0].length;
|
1012 |
for (int i=1; i<dim; i++) nrs = Math.min(nrs, samples[i].length); |
1013 |
|
1014 |
if (nrs <= dim) throw new SetException("DelaunayClarkson: " |
1015 |
+"not enough samples");
|
1016 |
if (dim > MAXDIM) throw new SetException("DelaunayClarkson: " |
1017 |
+"dimension bound MAXDIM exceeded");
|
1018 |
|
1019 |
// copy samples
|
1020 |
site_blocks = new double[dim][nrs]; |
1021 |
for (int j=0; j<dim; j++) { |
1022 |
System.arraycopy(samples[j], 0, site_blocks[j], 0, nrs); |
1023 |
} |
1024 |
|
1025 |
/* WLH 29 Jan 98 - scale samples values as discussed in Delaunay.factory
|
1026 |
for (int j=0; j<dim; j++) {
|
1027 |
for (int kk=0; kk<nrs; kk++) {
|
1028 |
site_blocks[j][kk] = 100.0f * samples[j][kk];
|
1029 |
}
|
1030 |
}
|
1031 |
*/
|
1032 |
|
1033 |
exact_bits = (int) (DBL_MANT_DIG*Math.log(FLT_RADIX)/ln2); |
1034 |
b_err_min = DBL_EPSILON*MAXDIM*(1<<MAXDIM)*MAXDIM*3.01; |
1035 |
b_err_min_sq = b_err_min * b_err_min; |
1036 |
|
1037 |
cdim = 0;
|
1038 |
rdim = dim+1;
|
1039 |
if (rdim > MAXDIM) throw new SetException( |
1040 |
"dimension bound MAXDIM exceeded; rdim="+rdim+"; dim="+dim); |
1041 |
|
1042 |
pnb = basis_s_list != NOVAL ? basis_s_list : new_block_basis_s(); |
1043 |
pnb_bn = basis_s_list_bn; |
1044 |
basis_s_list = bbt_next[pnb_bn][pnb]; |
1045 |
basis_s_list_bn = bbt_next_bn[pnb_bn][pnb]; |
1046 |
bbt_next[pnb_bn][pnb] = NOVAL; |
1047 |
|
1048 |
ttbp = basis_s_list != NOVAL ? basis_s_list : new_block_basis_s(); |
1049 |
ttbp_bn = basis_s_list_bn; |
1050 |
basis_s_list = bbt_next[ttbp_bn][ttbp]; |
1051 |
basis_s_list_bn = bbt_next_bn[ttbp_bn][ttbp]; |
1052 |
bbt_next[ttbp_bn][ttbp] = NOVAL; |
1053 |
bbt_ref_count[ttbp_bn][ttbp] = 1;
|
1054 |
bbt_lscale[ttbp_bn][ttbp] = -1;
|
1055 |
bbt_sqa[ttbp_bn][ttbp] = 0;
|
1056 |
bbt_sqb[ttbp_bn][ttbp] = 0;
|
1057 |
for (int j=0; j<2*rdim; j++) bbt_vecs[ttbp_bn][j][ttbp] = 0; |
1058 |
|
1059 |
root = NOVAL; |
1060 |
p = INFINITY; |
1061 |
ib = (basis_s_list != NOVAL) ? basis_s_list : new_block_basis_s(); |
1062 |
ib_bn = basis_s_list_bn; |
1063 |
basis_s_list = bbt_next[ib_bn][ib]; |
1064 |
basis_s_list_bn = bbt_next_bn[ib_bn][ib]; |
1065 |
bbt_ref_count[ib_bn][ib] = 1;
|
1066 |
bbt_vecs[ib_bn][2*rdim-1][ib] = bbt_vecs[ib_bn][rdim-1][ib] = 1; |
1067 |
bbt_sqa[ib_bn][ib] = bbt_sqb[ib_bn][ib] = 1;
|
1068 |
|
1069 |
root = (simplex_list != NOVAL) ? simplex_list : new_block_simplex(); |
1070 |
root_bn = simplex_list_bn; |
1071 |
simplex_list = sbt_next[root_bn][root]; |
1072 |
simplex_list_bn = sbt_next_bn[root_bn][root]; |
1073 |
|
1074 |
ch_root = root; |
1075 |
ch_root_bn = root_bn; |
1076 |
|
1077 |
s = (simplex_list != NOVAL) ? simplex_list : new_block_simplex(); |
1078 |
s_bn = simplex_list_bn; |
1079 |
simplex_list = sbt_next[s_bn][s]; |
1080 |
simplex_list_bn = sbt_next_bn[s_bn][s]; |
1081 |
sbt_next[s_bn][s] = sbt_next[root_bn][root]; |
1082 |
sbt_next_bn[s_bn][s] = sbt_next_bn[root_bn][root]; |
1083 |
sbt_visit[s_bn][s] = sbt_visit[root_bn][root]; |
1084 |
sbt_mark[s_bn][s] = sbt_mark[root_bn][root]; |
1085 |
sbt_normal[s_bn][s] = sbt_normal[root_bn][root]; |
1086 |
sbt_normal_bn[s_bn][s] = sbt_normal_bn[root_bn][root]; |
1087 |
sbt_peak_vert[s_bn][s] = sbt_peak_vert[root_bn][root]; |
1088 |
sbt_peak_simp[s_bn][s] = sbt_peak_simp[root_bn][root]; |
1089 |
sbt_peak_simp_bn[s_bn][s] = sbt_peak_simp_bn[root_bn][root]; |
1090 |
sbt_peak_basis[s_bn][s] = sbt_peak_basis[root_bn][root]; |
1091 |
sbt_peak_basis_bn[s_bn][s] = sbt_peak_basis_bn[root_bn][root]; |
1092 |
for (int i=0; i<rdim; i++) { |
1093 |
sbt_neigh_vert[s_bn][i][s] = sbt_neigh_vert[root_bn][i][root]; |
1094 |
sbt_neigh_simp[s_bn][i][s] = sbt_neigh_simp[root_bn][i][root]; |
1095 |
sbt_neigh_simp_bn[s_bn][i][s] = sbt_neigh_simp_bn[root_bn][i][root]; |
1096 |
sbt_neigh_basis[s_bn][i][s] = sbt_neigh_basis[root_bn][i][root]; |
1097 |
sbt_neigh_basis_bn[s_bn][i][s] = sbt_neigh_basis_bn[root_bn][i][root]; |
1098 |
} |
1099 |
for (int i=0;i<cdim;i++) { |
1100 |
q = sbt_neigh_basis[root_bn][i][root]; |
1101 |
q_bn = sbt_neigh_basis_bn[root_bn][i][root]; |
1102 |
if (q != NOVAL) bbt_ref_count[q_bn][q]++;
|
1103 |
} |
1104 |
sbt_peak_vert[root_bn][root] = p; |
1105 |
sbt_peak_simp[root_bn][root] = s; |
1106 |
sbt_peak_simp_bn[root_bn][root] = s_bn; |
1107 |
sbt_peak_simp[s_bn][s] = root; |
1108 |
sbt_peak_simp_bn[s_bn][s] = root_bn; |
1109 |
while (cdim < rdim) {
|
1110 |
int oof = 0; |
1111 |
|
1112 |
if (s_num == 0) p = 0; |
1113 |
else p++;
|
1114 |
for (int i=0; i<dim; i++) { |
1115 |
site_blocks[i][p] = (double) Math.floor(site_blocks[i][p]+0.5); |
1116 |
} |
1117 |
s_num++; |
1118 |
pnum = (s_num*dim-1)/dim + 2; |
1119 |
|
1120 |
cdim++; |
1121 |
sbt_neigh_vert[root_bn][cdim-1][root] = sbt_peak_vert[root_bn][root];
|
1122 |
|
1123 |
q = sbt_neigh_basis[root_bn][cdim-1][root];
|
1124 |
q_bn = sbt_neigh_basis_bn[root_bn][cdim-1][root];
|
1125 |
if (q != NOVAL && --bbt_ref_count[q_bn][q] == 0) { |
1126 |
bbt_next[q_bn][q] = basis_s_list; |
1127 |
bbt_next_bn[q_bn][q] = basis_s_list_bn; |
1128 |
bbt_ref_count[q_bn][q] = 0;
|
1129 |
bbt_lscale[q_bn][q] = 0;
|
1130 |
bbt_sqa[q_bn][q] = 0;
|
1131 |
bbt_sqb[q_bn][q] = 0;
|
1132 |
for (int l=0; l<2*rdim; l++) bbt_vecs[q_bn][l][q] = 0; |
1133 |
|
1134 |
basis_s_list = q; |
1135 |
basis_s_list_bn = q_bn; |
1136 |
} |
1137 |
sbt_neigh_basis[root_bn][cdim-1][root] = NOVAL;
|
1138 |
|
1139 |
get_basis_sede(root, root_bn); |
1140 |
if (sbt_neigh_vert[root_bn][0][root] == INFINITY) oof = 1; |
1141 |
else {
|
1142 |
curt[0] = pnb;
|
1143 |
curt_bn[0] = pnb_bn;
|
1144 |
reduce(curt, curt_bn, p, root, root_bn, cdim); |
1145 |
pnb = curt[0];
|
1146 |
pnb_bn = curt_bn[0];
|
1147 |
if (bbt_sqa[pnb_bn][pnb] != 0) oof = 1; |
1148 |
else cdim--;
|
1149 |
} |
1150 |
if (oof != 0) extend_simplices(root, root_bn, voidp, voidp_bn); |
1151 |
else {
|
1152 |
search(root, root_bn, retp, retp_bn); |
1153 |
make_facets(retp[0], retp_bn[0], ret2p, ret2p_bn); |
1154 |
connect(ret2p[0], ret2p_bn[0]); |
1155 |
} |
1156 |
} |
1157 |
|
1158 |
for (int i=s_num; i<nrs; i++) { |
1159 |
p++; |
1160 |
s_num++; |
1161 |
for (int j=0; j<dim; j++) { |
1162 |
site_blocks[j][p] = (double) Math.floor(site_blocks[j][p]+0.5); |
1163 |
} |
1164 |
pnum = (s_num*dim-1)/dim + 2; |
1165 |
search(root, root_bn, retp, retp_bn); |
1166 |
make_facets(retp[0], retp_bn[0], ret2p, ret2p_bn); |
1167 |
connect(ret2p[0], ret2p_bn[0]); |
1168 |
} |
1169 |
|
1170 |
a3size = rdim*nrs; |
1171 |
a3s = new int[rdim][a3size+MAXDIM+1]; |
1172 |
visit_triang_gen(root, root_bn, 1, retp, retp_bn);
|
1173 |
visit_triang_gen(retp[0], retp_bn[0], 0, voidp, voidp_bn); |
1174 |
|
1175 |
// deallocate memory
|
1176 |
/* NOTE: If this deallocation is not performed, more points
|
1177 |
could theoretically be added to the triangulation later */
|
1178 |
site_blocks = null;
|
1179 |
st = null;
|
1180 |
st_bn = null;
|
1181 |
st2 = null;
|
1182 |
st2_bn = null;
|
1183 |
sbt_next = null;
|
1184 |
sbt_next_bn = null;
|
1185 |
sbt_visit = null;
|
1186 |
sbt_mark = null;
|
1187 |
sbt_normal = null;
|
1188 |
sbt_normal_bn = null;
|
1189 |
sbt_peak_vert = null;
|
1190 |
sbt_peak_simp = null;
|
1191 |
sbt_peak_simp_bn = null;
|
1192 |
sbt_peak_basis = null;
|
1193 |
sbt_peak_basis_bn = null;
|
1194 |
sbt_neigh_vert = null;
|
1195 |
sbt_neigh_simp = null;
|
1196 |
sbt_neigh_simp_bn = null;
|
1197 |
sbt_neigh_basis = null;
|
1198 |
sbt_neigh_basis_bn = null;
|
1199 |
bbt_next = null;
|
1200 |
bbt_next_bn = null;
|
1201 |
bbt_ref_count = null;
|
1202 |
bbt_lscale = null;
|
1203 |
bbt_sqa = null;
|
1204 |
bbt_sqb = null;
|
1205 |
bbt_vecs = null;
|
1206 |
|
1207 |
/* ********** END OF CONVERTED HULL CODE ********** */
|
1208 |
/* (but still inside constructor) */
|
1209 |
|
1210 |
// compute number of triangles or tetrahedra
|
1211 |
int[] nverts = new int[nrs]; |
1212 |
for (int i=0; i<nrs; i++) nverts[i] = 0; |
1213 |
int ntris = 0; |
1214 |
boolean positive;
|
1215 |
for (int i=0; i<nts; i++) { |
1216 |
positive = true;
|
1217 |
for (int j=0; j<rdim; j++) { |
1218 |
if (a3s[j][i] < 0) positive = false; |
1219 |
} |
1220 |
if (positive) {
|
1221 |
ntris++; |
1222 |
for (int j=0; j<rdim; j++) nverts[a3s[j][i]]++; |
1223 |
} |
1224 |
} |
1225 |
Vertices = new int[nrs][]; |
1226 |
for (int i=0; i<nrs; i++) Vertices[i] = new int[nverts[i]]; |
1227 |
for (int i=0; i<nrs; i++) nverts[i] = 0; |
1228 |
|
1229 |
// build Tri & Vertices components
|
1230 |
Tri = new int[ntris][rdim]; |
1231 |
int a, b, c, d;
|
1232 |
int itri = 0; |
1233 |
for (int i=0; i<nts; i++) { |
1234 |
positive = true;
|
1235 |
for (int j=0; j<rdim; j++) { |
1236 |
if (a3s[j][i] < 0) positive = false; |
1237 |
} |
1238 |
if (positive) {
|
1239 |
for (int j=0; j<rdim; j++) { |
1240 |
Vertices[a3s[j][i]][nverts[a3s[j][i]]++] = itri; |
1241 |
Tri[itri][j] = a3s[j][i]; |
1242 |
} |
1243 |
itri++; |
1244 |
} |
1245 |
} |
1246 |
|
1247 |
// Deallocate remaining helper information
|
1248 |
a3s = null;
|
1249 |
|
1250 |
// call more generic method for constructing Walk and Edges arrays
|
1251 |
finish_triang(samples); |
1252 |
} |
1253 |
|
1254 |
} |
1255 |
|