00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <math.h>
00021 #include <malloc.h>
00022 #include <stdio.h>
00023 #include <sys/types.h>
00024 #include <stdlib.h>
00025
00026 #include "bloomenthal.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 char * jbProcess::polygonize (
00057
00058 Implicit *in_f,
00059 double in_size,
00060 int in_bounds,
00061 gmVector3 x,
00062 int (*in_triproc)(int i1, int i2, int i3, jbVertices vertices))
00063 {
00064 int n;
00065 jbTest in, out;
00066
00067 f = in_f;
00068 triproc = in_triproc;
00069 size = in_size;
00070 bounds = in_bounds;
00071 delta = size/(double)(RES*RES);
00072
00073
00074 centers = (jbCenterlist **) mycalloc(HSIZE, sizeof(jbCenterlist *));
00075 corners = (jbCornerlist **) mycalloc(HSIZE, sizeof(jbCornerlist *));
00076 edges = (jbEdgelist **) mycalloc(2*HSIZE, sizeof(jbEdgelist *));
00077
00078 vertices.count = vertices.max = 0;
00079 vertices.ptr = NULL;
00080
00081
00082 srand(1);
00083 in = find(1 == 1, x);
00084 out = find(0 == 1, x);
00085 if (!in.ok || !out.ok) {
00086 freeprocess();
00087 if (!in.ok) printf ("in not ok\n");
00088 if (!out.ok) printf ("out not ok\n");
00089 return "can't find starting point";
00090 }
00091 start = converge(in.pt, out.pt, in.value);
00092
00093
00094 cubes = (jbCubes *) mycalloc(1, sizeof(jbCubes));
00095 cubes->cube.i = cubes->cube.j = cubes->cube.k = 0;
00096 cubes->next = NULL;
00097
00098
00099 for (n = 0; n < 8; n++)
00100 cubes->cube.corners[n] = \
00101 setcorner(BIT(n,2), BIT(n,1), BIT(n,0));
00102
00103 setcenter(0, 0, 0);
00104
00105 while (cubes != NULL) {
00106 jbCube c;
00107 jbCubes *temp = cubes;
00108 c = cubes->cube;
00109
00110
00111 if (!(dotet(&c, JB_LBN, JB_LTN, JB_RBN, JB_LBF) &&
00112 dotet(&c, JB_RTN, JB_LTN, JB_LBF, JB_RBN) &&
00113 dotet(&c, JB_RTN, JB_LTN, JB_LTF, JB_LBF) &&
00114 dotet(&c, JB_RTN, JB_RBN, JB_LBF, JB_RBF) &&
00115 dotet(&c, JB_RTN, JB_LBF, JB_LTF, JB_RBF) &&
00116 dotet(&c, JB_RTN, JB_LTF, JB_RTF, JB_RBF)))
00117 {
00118 freeprocess();
00119 return "aborted";
00120 }
00121
00122
00123 cubes = cubes->next;
00124 free((char *) temp);
00125
00126 testface(c.i-1, c.j, c.k, &c, JB_L, JB_LBN, JB_LBF, JB_LTN, JB_LTF);
00127 testface(c.i+1, c.j, c.k, &c, JB_R, JB_RBN, JB_RBF, JB_RTN, JB_RTF);
00128 testface(c.i, c.j-1, c.k, &c, JB_B, JB_LBN, JB_LBF, JB_RBN, JB_RBF);
00129 testface(c.i, c.j+1, c.k, &c, JB_T, JB_LTN, JB_LTF, JB_RTN, JB_RTF);
00130 testface(c.i, c.j, c.k-1, &c, JB_N, JB_LBN, JB_LTN, JB_RBN, JB_RTN);
00131 testface(c.i, c.j, c.k+1, &c, JB_F, JB_LBF, JB_LTF, JB_RBF, JB_RTF);
00132 }
00133 freeprocess();
00134
00135 return NULL;
00136 }
00137
00138 char * jbProcess::marchingcubes (
00139 Implicit *in_f,
00140 double in_size,
00141 gmVector3 x0, gmVector3 x1,
00142 int (*in_triproc)(int i1, int i2, int i3, jbVertices vertices))
00143 {
00144 int i,j,k,n,i1,j1,k1;
00145 jbCube cube;
00146 int pos;
00147
00148 f = in_f;
00149 triproc = in_triproc;
00150 size = in_size;
00151 bounds = 0;
00152 delta = size/(double)(RES*RES);
00153
00154
00155 centers = (jbCenterlist **) mycalloc(HSIZE, sizeof(jbCenterlist *));
00156 corners = (jbCornerlist **) mycalloc(HSIZE, sizeof(jbCornerlist *));
00157 edges = (jbEdgelist **) mycalloc(2*HSIZE, sizeof(jbEdgelist *));
00158
00159 vertices.count = vertices.max = 0;
00160 vertices.ptr = NULL;
00161
00162
00163
00164
00165 srand(1);
00166 start = x1 - size*gmVector3(.5,.5,.5) - 0.001*size*gmVector3(RAND(),RAND(),RAND());
00167
00168 i1 = (int)((x1[0] - x0[0])/size);
00169 j1 = (int)((x1[1] - x0[1])/size);
00170 k1 = (int)((x1[2] - x0[2])/size);
00171
00172 for (k = 0; k <= k1; k++) {
00173 for (j = 0; j <= j1; j++) {
00174 for (i = 0; i <= i1; i++) {
00175
00176 cube.i = i;
00177 cube.j = j;
00178 cube.k = k;
00179
00180 pos = 0;
00181
00182
00183 for (n = 0; n < 8; n++) {
00184 cube.corners[n] = setcorner(i+BIT(n,2), j+BIT(n,1), k+BIT(n,0));
00185 if (cube.corners[n]->value > 0.0) pos++;
00186 }
00187
00188 if (pos == 0 || pos == 8)
00189 continue;
00190
00191 dotet(&cube, JB_LBN, JB_LTN, JB_RBN, JB_LBF);
00192 dotet(&cube, JB_RTN, JB_LTN, JB_LBF, JB_RBN);
00193 dotet(&cube, JB_RTN, JB_LTN, JB_LTF, JB_LBF);
00194 dotet(&cube, JB_RTN, JB_RBN, JB_LBF, JB_RBF);
00195 dotet(&cube, JB_RTN, JB_LBF, JB_LTF, JB_RBF);
00196 dotet(&cube, JB_RTN, JB_LTF, JB_RTF, JB_RBF);
00197 }
00198 }
00199 }
00200
00201 freeprocess();
00202
00203 return NULL;
00204 }
00205
00206
00207
00208
00209 void jbProcess::freeprocess() {
00210 int index;
00211 jbCornerlist *l, *lnext;
00212 jbCenterlist *cl, *clnext;
00213 jbEdgelist *edge, *edgenext;
00214
00215 for (index = 0; index < HSIZE; index++)
00216 for (l = corners[index]; l; l = lnext) {
00217 lnext = l->next;
00218 free((char *) l);
00219 }
00220 for (index = 0; index < HSIZE; index++)
00221 for (cl = centers[index]; cl; cl = clnext) {
00222 clnext = cl->next;
00223 free((char *) cl);
00224 }
00225 for (index = 0; index < 2*HSIZE; index++)
00226 for (edge = edges[index]; edge; edge = edgenext) {
00227 edgenext = edge->next;
00228 free((char *) edge);
00229 }
00230 free((char *) edges);
00231 free((char *) corners);
00232 free((char *) centers);
00233 if (vertices.ptr)
00234 free((char *) vertices.ptr);
00235 }
00236
00237
00238
00239
00240
00241 void jbProcess::testface (
00242 int i, int j, int k,
00243 jbCube *old,
00244 int face, int c1, int c2, int c3, int c4)
00245 {
00246 jbCube newcube;
00247 jbCubes *oldcubes = cubes;
00248 static int facebit[6] = {2, 2, 1, 1, 0, 0};
00249 int n, pos = old->corners[c1]->value > 0.0 ? 1 : 0;
00250 int bit = facebit[face];
00251
00252
00253 if ((old->corners[c2]->value > 0) == pos &&
00254 (old->corners[c3]->value > 0) == pos &&
00255 (old->corners[c4]->value > 0) == pos) return;
00256 if (abs(i) > bounds || abs(j) > bounds || abs(k) > bounds)
00257 return;
00258 if (setcenter(i, j, k)) return;
00259
00260
00261 newcube.i = i;
00262 newcube.j = j;
00263 newcube.k = k;
00264 for (n = 0; n < 8; n++) newcube.corners[n] = NULL;
00265 newcube.corners[FLIP(c1, bit)] = old->corners[c1];
00266 newcube.corners[FLIP(c2, bit)] = old->corners[c2];
00267 newcube.corners[FLIP(c3, bit)] = old->corners[c3];
00268 newcube.corners[FLIP(c4, bit)] = old->corners[c4];
00269 for (n = 0; n < 8; n++)
00270 if (newcube.corners[n] == NULL) newcube.corners[n] =
00271 setcorner(i+BIT(n,2), j+BIT(n,1), k+BIT(n,0));
00272
00273
00274 cubes = (jbCubes *) mycalloc(1, sizeof(jbCubes));
00275 cubes->cube = newcube;
00276 cubes->next = oldcubes;
00277 }
00278
00279
00280
00281
00282 gmVector3 jbProcess::setpoint (int i, int j, int k)
00283 {
00284 return start - size*gmVector3(i-0.5,j-0.5,k-0.5);
00285 }
00286
00287
00288
00289
00290
00291 jbCornerlist * jbProcess::setcorner (int i, int j, int k)
00292 {
00293
00294 int index = HASH(i, j, k);
00295 jbCornerlist *l = corners[index];
00296 gmVector3 pt;
00297
00298 for (; l != NULL; l = l->next)
00299 if (l->i == i && l->j == j && l->k == k) return l;
00300
00301 pt = setpoint (i, j, k);
00302 l = (jbCornerlist *) mycalloc(1, sizeof(jbCornerlist));
00303 l->i = i; l->j = j; l->k = k;
00304 l->value = f->proc(pt);
00305 l->next = corners[index];
00306 corners[index] = l;
00307 return l;
00308 }
00309
00310
00311
00312
00313 jbTest jbProcess::find(int sign, gmVector3 x)
00314 {
00315 int i;
00316 jbTest test;
00317 double range = size;
00318
00319 test.ok = 1;
00320 for (i = 0; i < 10000; i++) {
00321 test.pt = x + range*gmVector3(RAND()-0.5,RAND()-0.5,RAND()-0.5);
00322 test.value = f->proc(test.pt);
00323 if (sign == (test.value > 0.0)) return test;
00324 range = range*1.0005;
00325 }
00326 test.ok = 0;
00327 return test;
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 int jbProcess::dotet (jbCube *cube, int c1, int c2, int c3, int c4) {
00339 jbCornerlist *a = cube->corners[c1],
00340 *b = cube->corners[c2],
00341 *c = cube->corners[c3],
00342 *d = cube->corners[c4];
00343 int index = 0, apos, bpos, cpos, dpos, e1, e2, e3, e4, e5, e6;
00344
00345 if (apos = (a->value > 0.0)) index += 8;
00346 if (bpos = (b->value > 0.0)) index += 4;
00347 if (cpos = (c->value > 0.0)) index += 2;
00348 if (dpos = (d->value > 0.0)) index += 1;
00349
00350 if (apos != bpos) e1 = vertid(a, b);
00351 if (apos != cpos) e2 = vertid(a, c);
00352 if (apos != dpos) e3 = vertid(a, d);
00353 if (bpos != cpos) e4 = vertid(b, c);
00354 if (bpos != dpos) e5 = vertid(b, d);
00355 if (cpos != dpos) e6 = vertid(c, d);
00356
00357 switch (index) {
00358 case 1: return triproc(e5, e6, e3, vertices);
00359 case 2: return triproc(e2, e6, e4, vertices);
00360 case 3: return triproc(e3, e5, e4, vertices) &&
00361 triproc(e3, e4, e2, vertices);
00362 case 4: return triproc(e1, e4, e5, vertices);
00363 case 5: return triproc(e3, e1, e4, vertices) &&
00364 triproc(e3, e4, e6, vertices);
00365 case 6: return triproc(e1, e2, e6, vertices) &&
00366 triproc(e1, e6, e5, vertices);
00367 case 7: return triproc(e1, e2, e3, vertices);
00368 case 8: return triproc(e1, e3, e2, vertices);
00369 case 9: return triproc(e1, e5, e6, vertices) &&
00370 triproc(e1, e6, e2, vertices);
00371 case 10: return triproc(e1, e3, e6, vertices) &&
00372 triproc(e1, e6, e4, vertices);
00373 case 11: return triproc(e1, e5, e4, vertices);
00374 case 12: return triproc(e3, e2, e4, vertices) &&
00375 triproc(e3, e4, e5, vertices);
00376 case 13: return triproc(e6, e2, e4, vertices);
00377 case 14: return triproc(e5, e3, e6, vertices);
00378 }
00379 return 1;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388 char *mycalloc (int nitems, int nbytes) {
00389 char *ptr = (char *) calloc(nitems, nbytes);
00390 if (ptr != NULL) return ptr;
00391 fprintf(stderr, "can't calloc %d bytes\n", nitems*nbytes);
00392 exit(1);
00393 }
00394
00395
00396
00397
00398
00399 int jbProcess::setcenter(int i, int j, int k) {
00400 int index = HASH(i, j, k);
00401 jbCenterlist *newlist, *l, *q = centers[index];
00402
00403 for (l = q; l != NULL; l = l->next)
00404 if (l->i == i && l->j == j && l->k == k) return 1;
00405 newlist = (jbCenterlist *) mycalloc(1, sizeof(jbCenterlist));
00406 newlist->i = i; newlist->j = j; newlist->k = k; newlist->next = q;
00407 centers[index] = newlist;
00408 return 0;
00409 }
00410
00411
00412
00413
00414 void jbProcess::setedge (int i1, int j1, int k1, int i2, int j2, int k2, int vid) {
00415 unsigned int index;
00416 jbEdgelist *newlist;
00417
00418 if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) {
00419 int t=i1; i1=i2; i2=t; t=j1; j1=j2; j2=t; t=k1; k1=k2; k2=t;
00420 }
00421 index = HASH(i1, j1, k1) + HASH(i2, j2, k2);
00422 newlist = (jbEdgelist *) mycalloc(1, sizeof(jbEdgelist));
00423 newlist->i1 = i1; newlist->j1 = j1; newlist->k1 = k1;
00424 newlist->i2 = i2; newlist->j2 = j2; newlist->k2 = k2;
00425 newlist->vid = vid;
00426 newlist->next = edges[index];
00427 edges[index] = newlist;
00428 }
00429
00430
00431
00432
00433 int jbProcess::getedge (int i1, int j1, int k1, int i2, int j2, int k2)
00434 {
00435 jbEdgelist *q;
00436 if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) {
00437 int t=i1; i1=i2; i2=t; t=j1; j1=j2; j2=t; t=k1; k1=k2; k2=t;
00438 }
00439 q = edges[HASH(i1, j1, k1)+HASH(i2, j2, k2)];
00440 for (; q != NULL; q = q->next)
00441 if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 &&
00442 q->i2 == i2 && q->j2 == j2 && q->k2 == k2)
00443 return q->vid;
00444 return -1;
00445 }
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 int jbProcess::vertid (jbCornerlist *c1, jbCornerlist *c2) {
00456 jbVertex v;
00457 gmVector3 a, b;
00458 int vid =
00459 getedge(c1->i, c1->j, c1->k, c2->i, c2->j, c2->k);
00460 if (vid != -1) return vid;
00461 a = setpoint (c1->i, c1->j, c1->k);
00462 b = setpoint (c2->i, c2->j, c2->k);
00463 v.position = converge (a, b, c1->value);
00464
00465 vid = vertices.add(v);
00466 setedge(c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid);
00467 return vid;
00468 }
00469
00470
00471
00472
00473 int jbVertices::add(jbVertex v) {
00474 int i;
00475 jbVertex *newv;
00476
00477 if (count == max) {
00478 max = count == 0 ? 10 : 2*count;
00479 newv = (jbVertex *) mycalloc((unsigned)max,sizeof(jbVertex));
00480 for (i = 0; i < count; i++) newv[i] = ptr[i];
00481 if (ptr != NULL) free((char *) ptr);
00482 ptr = newv;
00483 }
00484 ptr[count++] = v;
00485 return (count-1);
00486 }
00487
00488
00489
00490 gmVector3 jbProcess::converge (gmVector3 p1, gmVector3 p2, double v)
00491 {
00492 int i = 0;
00493 gmVector3 pos, neg, p;
00494
00495 if (v < 0) {
00496 pos = p2;
00497 neg = p1;
00498 }
00499 else {
00500 pos = p1;
00501 neg = p2;
00502 }
00503 for (;;) {
00504 p = 0.5*(pos+neg);
00505 if (i++ == RES) return p;
00506 if ((f->proc(p)) > 0.0) {
00507 pos = p;
00508 } else {
00509 neg = p;
00510 }
00511 }
00512 }