class threeedpoint
{
double x, y, z;
}
class Test
{
threeedpoint p;
double value;
int ok;
}
class Vertex
{
threeedpoint position, normal;
}
class Vertices
{
int count, max;
Vertex ptr;
}
class Corner
{
int i, j, k;
double x, y, z, value;
}
class Cube
{
int i, j, k;
Corner[] corners = new Corner[8];
}
class Cubes
{
Cube cube;
Cubes next;
}
class CenterList
{
int i, j, k;
CenterList next;
}
class CornerList
{
int i, j, k;
double value;
CornerList next;
}
class EdgeList
{
int i1, j1, k1, i2, j2, k2;
int vid;
EdgeList next;
}
class IntList
{
int i;
IntList next;
}
class IntLists
{
IntList list;
IntLists next;
}
class Implicit
{
int gntris;
int bounds, i1, i2, i3;
double size, delta;
threeedpoint start;
Vector cubes = new Vector();
Vector vertices = new Vector();
Vector centers = new Vector();
Vector corners = new Vector();
Vector edges = new Vector();
Vector gVertices = new Vector();
Vector tVertices = new Vector();
final int TET = 0;
final int NOTET = 1;
final int RES = 10;
final int L = 0;
final int R = 1;
final int B = 2;
final int T = 3;
final int N = 4;
final int F = 5;
final int LBN = 0;
final int LBF = 1;
final int LTN = 2;
final int LTF = 3;
final int RBN = 4;
final int RBF = 5;
final int RTN = 6;
final int RTF = 7;
final int HASHBIT = 5;
final int LB = 0;
final int LT = 1;
final int LN = 2;
final int LF = 3;
final int RB = 4;
final int RT = 5;
final int RN = 6;
final int RF = 7;
final int BN = 8;
final int BF = 9;
final int TN = 10;
final int TF = 11;
static Vector Cubetable= new Vector(256);
int[] Corner1 = new int[12];
int[] Corner2 = new int[12];
int[] leftface = new int[12];
int[] rightface = new int[12];
int RAND()
{
return (int)Math.random();
}
int HASHSIZE()
{
return (1<<(3*HASHBIT));
}
int MASK()
{
return ((1<<HASHBIT)-1);
}
int HASH(int i, int j, int k)
{
return ((((((i)&MASK())<<HASHBIT)|((j)&MASK()))<<HASHBIT)|((k)&MASK()));
}
int BIT(int i, int bit)
{
return (((i)>>(bit))&1);
}
int FLIP(int i, int bit)
{
return ((i)^1<<(bit));
}
double sphere (double x, double y, double z)
{
double rsq = x*x+y*y+z*z;
return 1.0/(rsq < 0.00001? 0.00001 : rsq);
}
double blob (double x, double y, double z)
{
return 4.0-sphere(x+1.0,y,z)-sphere(x,y+1.0,z)-sphere(x,y,z+1.0);
}
int triproc(int i1, int i2, int i3, Vector tVertices)
{
gVertices = tVertices;
gntris++;
return 1;
}
String polygonize (double size, double bounds, double x, double y, double
z, int mode)
{
int n;
int noabort=0;
Test in = new Test();
Test out = new Test();
makeCubetable();
in = find(1, x, y, z);
out = find(0, x, y, z);
Cube c = new Cube();
cubes.addElement(c);
while (cubes != null)
{
Cubes temp = new Cubes();
doCube(c);
if (noabort==1)
return "aborted";
Testface(c.i-1, c.j, c.k, c, L, LBN, LBF, LTN, LTF);
Testface(c.i+1, c.j, c.k, c, R, RBN, RBF, RTN, RTF);
Testface(c.i, c.j-1, c.k, c, B, LBN, LBF, RBN, RBF);
Testface(c.i, c.j+1, c.k, c, T, LTN, LTF, RTN, RTF);
Testface(c.i, c.j, c.k-1, c, N, LBN, LTN, RBN, RTN);
Testface(c.i, c.j, c.k+1, c, F, LBF, LTF, RBF, RTF);
}
return null;
}
void Testface (int i, int j, int k, Cube old, int face, int c1, int
c2, int c3, int c4)
{
Cube newCube = new Cube();
Cubes oldCubes = new Cubes();
int[] facebit = new int[6];
int n, pos = old.corners[c1].value > 0.0 ? 1 : 0,
bit = facebit[face];
if (((old.corners[c2].value > 0)) &&
((old.corners[c3].value > 0)) &&
((old.corners[c4].value > 0)))
return;
if (Math.abs(i) > bounds || Math.abs(j) > bounds
|| Math.abs(k) > bounds)
return;
for (n = 0; n < 8; n++)
newCube.corners[n] = null;
newCube.corners[FLIP(c1, bit)] = old.corners[c1];
newCube.corners[FLIP(c2, bit)] = old.corners[c2];
newCube.corners[FLIP(c3, bit)] = old.corners[c3];
newCube.corners[FLIP(c4, bit)] = old.corners[c4];
}
Corner setCorner(int i, int j, int k)
{
Corner c = new Corner();
int index = HASH(i, j, k);
CornerList l = new CornerList();
c.i = i;
c.x = start.x+((double)i-.5)*size;
c.j = j;
c.y = start.y+((double)j-.5)*size;
c.k = k;
c.z = start.z+((double)k-.5)*size;
for (; l != null; l = l.next)
if (l.i == i && l.j == j && l.k == k)
{
c.value = l.value;
return c;
}
l = new CornerList();
l.i = i;
l.j = j;
l.k = k;
c.value = blob(c.x, c.y, c.z);
l.value = c.value;
return c;
}
Test find(int sign, double x, double y, double z)
{
int i;
Test test = new Test();
double range = size;
test.ok = 1;
for (i = 0; i < 10000; i++)
{
test.p.x = x+range*(RAND()-0.5);
test.p.y = y+range*(RAND()-0.5);
test.p.z = z+range*(RAND()-0.5);
test.value = blob(test.p.x, test.p.y, test.p.z);
if(sign == test.value )
return test;
range = range*1.0005;
}
test.ok = 0;
return test;
}
int dotet(Cube c0, int c1, int c2, int c3, int c4)
{
Corner a = new Corner();
Corner b = new Corner();
Corner c = new Corner();
Corner d = new Corner();
int index =0;
int apos=0;
int bpos=0;
int cpos=0;
int dpos=0;
int e1=0;
int e2=0;
int e3=0;
int e4=0;
int e5=0;
int e6=0;
if (apos > 0.0)
index += 8;
if (bpos > 0.0)
index += 4;
if (cpos > 0.0)
index += 2;
if (dpos > 0.0)
index += 1;
if (apos != bpos)
e1 = vertid(a, b);
if (apos != cpos)
e2 = vertid(a, c);
if (apos != dpos)
e3 = vertid(a, d);
if (bpos != cpos)
e4 = vertid(b, c);
if (bpos != dpos)
e5 = vertid(b, d);
if (cpos != dpos)
e6 = vertid(c, d);
switch (index)
{
case 1:
return triproc(e5, e6, e3, vertices);
case 2:
return triproc(e2, e6, e4, vertices);
case 3:
return triproc(e3, e5, e4, vertices);
case 4:
return triproc(e1, e4, e5, vertices);
case 5:
return triproc(e3, e1, e4, vertices);
case 6:
return triproc(e1, e2, e6, vertices);
case 7:
return triproc(e1, e2, e3, vertices);
case 8:
return triproc(e1, e3, e2, vertices);
case 9:
return triproc(e1, e5, e6, vertices);
case 10:
return triproc(e1, e3, e6, vertices);
case 11:
return triproc(e1, e5, e4, vertices);
case 12:
return triproc(e3, e2, e4, vertices);
case 13:
return triproc(e6, e2, e4, vertices);
case 14:
return triproc(e5, e3, e6, vertices);
}
return 1;
}
int doCube(Cube c)
{
IntLists polys;
int i, index = 0;
for (i = 0; i < 8; i++)
if (c.corners[i].value > 0.0)
index += (1<<i);
for (i = 0; i <8; i++)
{
IntList edges;
int a = -1, b = -1, count = 0;
for (i=0; i<8;i++)
{
if (count < 3)
a = b;
}
}
return 1;
}
int nextcwedge(int edge, int face)
{
switch (edge)
{
case LB:
return (face == L)? LF : BN;
case LT:
return (face == L)? LN : TF;
case LN:
return (face == L)? LB : TN;
case LF:
return (face == L)? LT : BF;
case RB:
return (face == R)? RN : BF;
case RT:
return (face == R)? RF : TN;
case RN:
return (face == R)? RT : BN;
case RF:
return (face == R)? RB : TF;
case BN:
return (face == B)? RB : LN;
case BF:
return (face == B)? LB : RF;
case TN:
return (face == T)? LT : RN;
case TF:
return (face == T)? RT : LF;
default:
return 1;
}
}
int otherface (int edge, int face)
{
int other = leftface[edge];
return face == other? rightface[edge] : other;
}
void makeCubetable()
{
int i, e, c;
int[] done= new int[12];
int[] pos = new int[8];
for (i = 0; i < 256; i++)
{
for (e = 0; e < 12; e++)
done[e] = 0;
for (c = 0; c < 8; c++)
pos[c] = BIT(i, c);
for (e = 0; e < 12; e++)
{
IntList ints = new IntList();
ints.i = 0;
IntLists lists = new IntLists();
int start = e;
int edge = e;
int face = pos[Corner1[e]];
edge = nextcwedge(edge, face);
done[edge] = 1;
if(pos[Corner1[edge]] != pos[Corner2[edge]])
{
IntList tmp = new IntList();
tmp.i = ints.i;
ints.i = edge;
ints.next = tmp;
if (edge == start)
break;
face = otherface(edge, face);
}
lists.list = ints;
}
}
}
int setcenter(CenterList table, int i, int j, int k)
{
int index = HASH(i, j, k);
CenterList newList, l;
CenterList q = new CenterList();
for (l = q; l != null; l = l.next)
if (l.i == i && l.j == j && l.k == k)
return 1;
newList = new CenterList();
newList.i = i;
newList.j = j;
newList.k = k;
newList.next = q;
return 0;
}
void setedge (EdgeList table, int i1, int j1, int k1, int i2, int j2,
int k2, int vid)
{
int index;
EdgeList newEdgeList;
if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2
&& k1>k2))))
{
int t=i1; i1=i2; i2=t; t=j1; j1=j2; j2=t; t=k1; k1=k2; k2=t;
}
index = HASH(i1, j1, k1) + HASH(i2, j2, k2);
newEdgeList = new EdgeList();
newEdgeList.i1 = i1;
newEdgeList.j1 = j1;
newEdgeList.k1 = k1;
newEdgeList.i2 = i2;
newEdgeList.j2 = j2;
newEdgeList.k2 = k2;
newEdgeList.vid = vid;
}
int getedge (EdgeList table, int i1, int j1, int k1, int i2, int j2,
int k2)
{
EdgeList q= new EdgeList();
if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2
&& k1>k2))))
{
int t=i1;
i1=i2;
i2=t;
t=j1;
j1=j2;
j2=t;
t=k1;
k1=k2;
k2=t;
}
for (; q != null; q = q.next)
if (q.i1 == i1 && q.j1 == j1 && q.k1 == k1 &&
q.i2 == i2 && q.j2 == j2 &&
q.k2 == k2)
return q.vid;
return -1;
}
int vertid (Corner c1, Corner c2)
{
Vertex v = new Vertex();
threeedpoint a= new threeedpoint();
threeedpoint b= new threeedpoint();
a.x = c1.x;
a.y = c1.y;
a.z = c1.z;
b.x = c2.x;
b.y = c2.y;
b.z = c2.z;
converge(a, b, c1.value, v.position);
vnormal(v.position, v.normal);
return (int)c1.value;
}
void addtoVertices (Vertices vlist, Vertex v)
{
if (vlist.count == vlist.max)
{
int i;
Vertex newVertex;
vlist.max = vlist.count == 0 ? 10 : 2*vlist.count;
newVertex = new Vertex();
for (i = 0; i < vlist.count; i++)
vlist.ptr = newVertex;
}
}
void vnormal (threeedpoint point, threeedpoint v)
{
double f = blob(point.x, point.y, point.z);
v.x = blob(point.x+v.x, point.y, point.z)-f;
v.y = blob(point.x, point.y+v.y, point.z)-f;
v.z = blob(point.x, point.y, point.z+v.z)-f;
f = Math.sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
if (f != 0.0)
{
v.x /= f;
v.y /= f;
v.z /= f;
}
}
void converge (threeedpoint p1, threeedpoint p2, double v, threeedpoint
p)
{
int i = 0;
threeedpoint pos = new threeedpoint();
threeedpoint neg = new threeedpoint();
if (v < 0)
{
pos.x = p2.x;
pos.y = p2.y;
pos.z = p2.z;
neg.x = p1.x;
neg.y = p1.y;
neg.z = p1.z;
}
else
{
pos.x = p1.x;
pos.y = p1.y;
pos.z = p1.z;
neg.x = p2.x;
neg.y = p2.y;
neg.z = p2.z;
}
p.x = 0.5*(pos.x + neg.x);
p.y = 0.5*(pos.y + neg.y);
p.z = 0.5*(pos.z + neg.z);
if(i++ == RES)
return;
if ((blob(p.x, p.y, p.z)) > 0.0)
{
pos.x = p.x;
pos.y = p.y;
pos.z = p.z;
}
else
{
neg.x = p.x;
neg.y = p.y;
neg.z = p.z;
}
}
}