// Decompiled by Jad v1.5.7b. Copyright 1997-99 Pavel Kouznetsov.
|
// Jad home page: http://www.geocities.com/SiliconValley/Bridge/8617/jad.html
|
// Decompiler options: packimports(3)
|
// Source File Name: ImplicitTiler.java
|
import java.io.PrintStream;
|
import java.util.Vector;
|
import java.util.Iterator;
|
import java.util.PriorityQueue;
|
|
class ImplicitTiler implements Simplex.Solid
|
{
|
// Simplex.Solid
|
public boolean inside(double x, double y, double z)
|
{
|
return implicit.inside(x, y, z, false); // true);
|
}
|
|
public void push(Simplex simplex)
|
{
|
//assert (!simplexStack.contains(simplex));
|
//assert (!simplex.postpone);
|
{
|
//System.out.println("Remove = " + simplex);
|
//simplexStack.remove(simplex);
|
//}
|
//System.out.println("Push = " + simplex);
|
simplexStack.offer(simplex);
|
}
|
}
|
|
static public void DumpStack()
|
{
|
Iterator inter = simplexStack.iterator();
|
|
while (inter.hasNext())
|
{
|
Simplex si = (Simplex) inter.next();
|
|
System.out.println("stack contains " + si);
|
}
|
}
|
|
public void push(Vector simplex)
|
{
|
for (int i = 0; i < simplex.size(); i++)
|
{
|
push((Simplex) simplex.get(i));
|
}
|
}
|
|
public int MinDepth()
|
{
|
return (int) cellSize;
|
}
|
|
public int MaxDepth()
|
{
|
return (int) cellSize2;
|
}
|
|
public double Tolerance()
|
{
|
return 0; // tolerance;
|
}
|
//boolean DEBUG = true; // false;
|
boolean DEBUG = false;
|
double x[] = new double[2];
|
double y[] = new double[2];
|
double z[] = new double[2];
|
static int SURFACEID = 0;
|
static int VOLUMEID = 1;
|
static int INNERID = 2;
|
static int OUTERID = 3;
|
static int BOUNDARYID = 4;
|
|
ImplicitTiler(Object3D imp, int genType, boolean genNormals, boolean trim, boolean stripify, double size, double size2, double tol, boolean interval)
|
{
|
if (genType == SURFACEID)
|
{
|
Simplex.SURFACE = true;
|
Simplex.SOLID = false;
|
Simplex.BOUNDARY = false;
|
}
|
|
if (genType == VOLUMEID)
|
{
|
Simplex.SURFACE = true;
|
Simplex.SOLID = true;
|
Simplex.BOUNDARY = false;
|
}
|
if (genType == INNERID)
|
{
|
Simplex.SURFACE = false;
|
Simplex.SOLID = true;
|
Simplex.BOUNDARY = false;
|
}
|
if (genType == OUTERID)
|
{
|
Simplex.SURFACE = false;
|
Simplex.SOLID = true;
|
Simplex.BOUNDARY = true;
|
}
|
if (genType == BOUNDARYID)
|
{
|
Simplex.SURFACE = false;
|
Simplex.SOLID = false;
|
Simplex.BOUNDARY = true;
|
}
|
|
for (int i = 0; i < 5; i++)
|
{
|
interlist.add(new Vertex());
|
}
|
|
implicit = imp;
|
cellSize = size;
|
cellSize2 = size2;
|
tolerance = tol;
|
bRep = new BoundaryRep();
|
minima = new cVector();
|
maxima = new cVector();
|
implicit.getBounds(minima, maxima, true); // false); // true);
|
if (minima.x != 1E10)
|
{
|
System.out.println("Bounds = " + minima + " - " + maxima);
|
//expandBounds(interval);
|
//minima.x -= 0.1; minima.y -= 0.1; minima.z -= 0.1;
|
//maxima.x += 0.1; maxima.y += 0.1; maxima.z += 0.1;
|
|
if (interval)
|
{
|
x[0] = minima.x - 0.01;
|
x[1] = maxima.x + 0.02;
|
y[0] = minima.y - 0.03;
|
y[1] = maxima.y + 0.04;
|
z[0] = minima.z - 0.05;
|
z[1] = maxima.z + 0.06;
|
|
double max = x[1] - x[0];
|
if (max < y[1] - y[0])
|
{
|
max = y[1] - y[0];
|
}
|
if (max < z[1] - z[0])
|
{
|
max = z[1] - z[0];
|
}
|
|
if (max > x[1] - x[0])
|
{
|
double diff = max - (x[1] - x[0]);
|
x[1] += diff / 2;
|
x[0] -= diff / 2;
|
}
|
|
if (max > y[1] - y[0])
|
{
|
double diff = max - (y[1] - y[0]);
|
y[1] += diff / 2;
|
y[0] -= diff / 2;
|
}
|
|
if (max > z[1] - z[0])
|
{
|
double diff = max - (z[1] - z[0]);
|
z[1] += diff / 2;
|
z[0] -= diff / 2;
|
}
|
|
//subdivide(x, y, z, 0);
|
//recurse(x, y, z, 0, 0);
|
simplexcube(x, y, z);
|
} else
|
{
|
iterate();
|
}
|
}
|
|
Simplex.solid = null;
|
|
//if (!trim) return;
|
|
//System.out.println("TRIM!!");
|
|
if (genNormals)
|
{
|
bRep.Trim(trim, true, false, stripify, true);
|
} else
|
{
|
if (tolerance == 0)
|
{
|
bRep.Trim(trim, false, false, stripify, true);
|
} else
|
{
|
// Merge normals: tolerance == 0 means use analytic,
|
// tolerance == 10 means use generated normals
|
BoundaryRep analytic = (BoundaryRep) Grafreed.clone(bRep);
|
BoundaryRep generated = (BoundaryRep) Grafreed.clone(bRep);
|
|
analytic.Trim(trim, false, false, stripify, true);
|
generated.Trim(trim, true, false, stripify, true);
|
bRep.Trim(trim, false, false, stripify, true); // or clone
|
|
System.out.println("#verticesA = " + analytic.VertexCount());
|
System.out.println("#verticesG = " + generated.VertexCount());
|
|
assert (bRep.VertexCount() == analytic.VertexCount());
|
assert (generated.VertexCount() == analytic.VertexCount());
|
|
for (int i = 0; i < bRep.VertexCount(); i++)
|
{
|
Vertex v = analytic.GetVertex(i);
|
|
double ax = v.norm.x;
|
double ay = v.norm.y;
|
double az = v.norm.z;
|
|
v = generated.GetVertex(i);
|
|
double gx = v.norm.x;
|
double gy = v.norm.y;
|
double gz = v.norm.z;
|
|
v = bRep.GetVertex(i);
|
|
double ndn = ax * gx + ay * gy + az * gz;
|
|
ndn = (ndn + 1) / 2;
|
|
double t = Math.pow(ndn, tolerance * tolerance * tolerance);
|
|
if (!(t > -0.0001 && t < 1.0001))
|
{
|
System.out.println("t = " + t);
|
assert (t > -0.0001 && t < 1.0001);
|
}
|
|
v.norm.x = t * ax + (1 - t) * gx;
|
v.norm.y = t * ay + (1 - t) * gy;
|
v.norm.z = t * az + (1 - t) * gz;
|
v.norm.normalize();
|
|
bRep.SetVertex(v, i);
|
}
|
}
|
}
|
}
|
|
private void expandBounds(boolean interval)
|
{
|
nCells = new int[3];
|
for (int i = 0; i < 3; i++)
|
{
|
double given = maxima.get(i) - minima.get(i);
|
if (interval)
|
{
|
double width = cellSize;
|
for (nCells[i] = 1; width < given; nCells[i] *= 2)
|
{
|
width *= 2;
|
}
|
|
minima.addEq(i, -(width - given) / 2);
|
maxima.addEq(i, (width - given) / 2);
|
} else
|
{
|
given += cellSize;
|
double width = cellSize;
|
for (nCells[i] = 1; width < given; nCells[i]++)
|
{
|
width += cellSize;
|
}
|
|
minima.addEq(i, -cellSize / 2);
|
maxima.set(i, minima.get(i) + (double) nCells[i] * cellSize);
|
}
|
}
|
|
}
|
|
void iterate()
|
{
|
boolean grid[][][] = new boolean[nCells[0] + 1][][];
|
int i = 0;
|
for (double x = minima.x; i <= nCells[0]; x += cellSize)
|
{
|
grid[i] = new boolean[nCells[1] + 1][];
|
int j = 0;
|
for (double y = minima.y; j <= nCells[1]; y += cellSize)
|
{
|
grid[i][j] = new boolean[nCells[2] + 1];
|
int k = 0;
|
for (double z = minima.z; k <= nCells[2]; z += cellSize)
|
{
|
grid[i][j][k] = implicit.inside(x, y, z, false); // true);
|
k++;
|
}
|
|
j++;
|
}
|
|
i++;
|
}
|
|
i = 0;
|
for (double x = minima.x; i < nCells[0]; x += cellSize)
|
{
|
int j = 0;
|
for (double y = minima.y; j < nCells[1]; y += cellSize)
|
{
|
int k = 0;
|
for (double z = minima.z; k < nCells[2]; z += cellSize)
|
{
|
if (heterogenous(grid, i, j, k))
|
{
|
xc8[0] = xc8[1] = xc8[2] = xc8[3] = x;
|
xc8[4] = xc8[5] = xc8[6] = xc8[7] = x + cellSize;
|
yc8[0] = yc8[1] = yc8[4] = yc8[5] = y;
|
yc8[2] = yc8[3] = yc8[6] = yc8[7] = y + cellSize;
|
zc8[0] = zc8[2] = zc8[4] = zc8[6] = z;
|
zc8[1] = zc8[3] = zc8[5] = zc8[7] = z + cellSize;
|
decompose();
|
}
|
k++;
|
}
|
|
j++;
|
}
|
|
i++;
|
}
|
|
}
|
|
boolean heterogenous(boolean grid[][][], int i, int j, int k)
|
{
|
inside8[0] = grid[i][j][k];
|
boolean or;
|
boolean and = or = inside8[0];
|
for (int m = 1; m < 8; m++)
|
{
|
int ii = m >= 4 ? i + 1 : i;
|
int jj = (m / 2) % 2 != 0 ? j + 1 : j;
|
int kk = m % 2 != 0 ? k + 1 : k;
|
inside8[m] = grid[ii][jj][kk];
|
and &= inside8[m];
|
or |= inside8[m];
|
}
|
|
return or && !and;
|
}
|
|
boolean heterogenous()
|
{
|
boolean or;
|
boolean and = or = inside8[0];
|
for (int m = 1; m < 8; m++)
|
{
|
and &= inside8[m];
|
or |= inside8[m];
|
}
|
|
return or && !and;
|
}
|
|
void subdivide(double x[], double y[], double z[], int dimension)
|
{
|
new Exception().printStackTrace();
|
System.exit(0);
|
boolean out[] = new boolean[2];
|
implicit.boxInside(x, y, z, out);
|
if (!out[0] && !out[1])
|
{
|
return;
|
}
|
if (out[0] && out[1])
|
{
|
accept(x, y, z);
|
return;
|
}
|
double half[] = new double[2];
|
switch (dimension)
|
{
|
case 0: // '\0'
|
half[0] = x[0];
|
half[1] = (x[0] + x[1]) / 2;
|
subdivide(half, y, z, 1);
|
half[0] = half[1];
|
half[1] = x[1];
|
subdivide(half, y, z, 1);
|
break;
|
|
case 1: // '\001'
|
half[0] = y[0];
|
half[1] = (y[0] + y[1]) / 2;
|
subdivide(x, half, z, 2);
|
half[0] = half[1];
|
half[1] = y[1];
|
subdivide(x, half, z, 2);
|
break;
|
|
case 2: // '\002'
|
half[0] = z[0];
|
half[1] = (z[0] + z[1]) / 2;
|
subdivide(x, y, half, 0);
|
half[0] = half[1];
|
half[1] = z[1];
|
subdivide(x, y, half, 0);
|
break;
|
}
|
}
|
|
void accept(double x[], double y[], double z[])
|
{
|
xc8[0] = xc8[1] = xc8[2] = xc8[3] = x[0];
|
xc8[4] = xc8[5] = xc8[6] = xc8[7] = x[1];
|
yc8[0] = yc8[1] = yc8[4] = yc8[5] = y[0];
|
yc8[2] = yc8[3] = yc8[6] = yc8[7] = y[1];
|
zc8[0] = zc8[2] = zc8[4] = zc8[6] = z[0];
|
zc8[1] = zc8[3] = zc8[5] = zc8[7] = z[1];
|
for (int i = 0; i < 8; i++)
|
{
|
inside8[i] = implicit.inside(xc8[i], yc8[i], zc8[i], false);
|
} // true);
|
|
decompose();
|
}
|
|
void recurse(double x[], double y[], double z[], int dimension, int depth)
|
{
|
if (depth >= 9) // mindepth3)
|
{
|
xc8[0] = xc8[1] = xc8[2] = xc8[3] = x[0];
|
xc8[4] = xc8[5] = xc8[6] = xc8[7] = x[1];
|
yc8[0] = yc8[1] = yc8[4] = yc8[5] = y[0];
|
yc8[2] = yc8[3] = yc8[6] = yc8[7] = y[1];
|
zc8[0] = zc8[2] = zc8[4] = zc8[6] = z[0];
|
zc8[1] = zc8[3] = zc8[5] = zc8[7] = z[1];
|
for (int i = 0; i < 8; i++)
|
{
|
inside8[i] = implicit.inside(xc8[i], yc8[i], zc8[i], false);
|
} // true);
|
|
if (!heterogenous())
|
{
|
return;
|
}
|
}
|
|
if (depth >= cellSize)
|
{
|
decompose();
|
return;
|
}
|
|
double half[] = new double[2];
|
switch (dimension)
|
{
|
case 0: // '\0'
|
half[0] = x[0];
|
half[1] = (x[0] + x[1]) / 2;
|
recurse(half, y, z, 1, depth + 1);
|
half[0] = half[1];
|
half[1] = x[1];
|
recurse(half, y, z, 1, depth + 1);
|
break;
|
|
case 1: // '\001'
|
half[0] = y[0];
|
half[1] = (y[0] + y[1]) / 2;
|
recurse(x, half, z, 2, depth + 1);
|
half[0] = half[1];
|
half[1] = y[1];
|
recurse(x, half, z, 2, depth + 1);
|
break;
|
|
case 2: // '\002'
|
half[0] = z[0];
|
half[1] = (z[0] + z[1]) / 2;
|
recurse(x, y, half, 0, depth + 1);
|
half[0] = half[1];
|
half[1] = z[1];
|
recurse(x, y, half, 0, depth + 1);
|
break;
|
}
|
}
|
static Vector cube8 = new Vector();
|
|
void simplexcube(double x[], double y[], double z[])
|
{
|
//Applet3D.tracein("simplexcube");
|
|
double cx = (x[0] + x[1]) / 2;
|
double cy = (y[0] + y[1]) / 2;
|
double cz = (z[0] + z[1]) / 2;
|
|
//double[] cube = new double[24];
|
|
for (int i = 0; i < 2; i++)
|
{
|
for (int j = 0; j < 2; j++)
|
{
|
for (int k = 0; k < 2; k++)
|
{
|
int index = ((i * 2 + j) * 2 + k) * 3;
|
cube[index] = x[i];
|
cube[index + 1] = y[j];
|
cube[index + 2] = z[k];
|
cube3[index / 3] = new Simplex.Point(x[i], y[j], z[k]);
|
}
|
}
|
}
|
|
Simplex.solid = this;
|
|
Simplex.Point c = new Simplex.Point(cx, cy, cz);
|
|
Simplex x0a = SimplexCube(c/*x,cy,cz*/, cube, 0, 1, 2); // x = 0
|
Simplex x0b = SimplexCube(c/*x,cy,cz*/, cube, 1, 2, 3);
|
Simplex y0a = SimplexCube(c/*x,cy,cz*/, cube, 0, 1, 5); // y = 0
|
Simplex y0b = SimplexCube(c/*x,cy,cz*/, cube, 0, 4, 5);
|
Simplex z0a = SimplexCube(c/*x,cy,cz*/, cube, 0, 4, 2); // z = 0
|
Simplex z0b = SimplexCube(c/*x,cy,cz*/, cube, 2, 4, 6);
|
Simplex x1a = SimplexCube(c/*x,cy,cz*/, cube, 4, 5, 6); // x = 1
|
Simplex x1b = SimplexCube(c/*x,cy,cz*/, cube, 5, 6, 7);
|
Simplex y1a = SimplexCube(c/*x,cy,cz*/, cube, 2, 3, 7); // y = 1
|
Simplex y1b = SimplexCube(c/*x,cy,cz*/, cube, 2, 6, 7);
|
Simplex z1a = SimplexCube(c/*x,cy,cz*/, cube, 1, 3, 7); // z = 1
|
Simplex z1b = SimplexCube(c/*x,cy,cz*/, cube, 1, 5, 7);
|
|
//Vector cube8 = new Vector();
|
cube8.clear();
|
cube8.add(x0a);
|
cube8.add(x0b);
|
cube8.add(y0a);
|
cube8.add(y0b);
|
cube8.add(z0a);
|
cube8.add(z0b);
|
cube8.add(x1a);
|
cube8.add(x1b);
|
cube8.add(y1a);
|
cube8.add(y1b);
|
cube8.add(z1a);
|
cube8.add(z1b);
|
|
Simplex.LinkSimplex(cube8);
|
Simplex.SetRoot(cube8);
|
|
push(cube8);
|
|
Subdivide();
|
|
//Simplex.SWAP = true;
|
|
//System.out.println("TEMP #faces = " + bRep.faces.size());
|
//System.out.println("TEMP #vertices = " + bRep.vertices.size());
|
|
Simplex.GenerateTriangles(cube8);
|
|
cube8.clear();
|
|
Simplex.SWAP = false;
|
|
/*
|
simplexcube0(cx,cy,cz, cube, 0,1,2); // x = 0
|
simplexcube0(cx,cy,cz, cube, 1,2,3);
|
simplexcube0(cx,cy,cz, cube, 0,1,5); // y = 0
|
simplexcube0(cx,cy,cz, cube, 0,4,5);
|
simplexcube0(cx,cy,cz, cube, 0,4,2); // z = 0
|
simplexcube0(cx,cy,cz, cube, 2,4,6);
|
simplexcube0(cx,cy,cz, cube, 4,5,6); // x = 1
|
simplexcube0(cx,cy,cz, cube, 5,6,7);
|
simplexcube0(cx,cy,cz, cube, 2,3,7); // y = 1
|
simplexcube0(cx,cy,cz, cube, 2,6,7);
|
simplexcube0(cx,cy,cz, cube, 1,3,7); // z = 1
|
simplexcube0(cx,cy,cz, cube, 1,5,7);
|
*/
|
//Applet3D.traceout();
|
}
|
static java.util.PriorityQueue simplexStack = new java.util.PriorityQueue();
|
|
void Subdivide()
|
{
|
while (simplexStack.size() > 0) // !simplexStack.empty())
|
{
|
Simplex simplex = (Simplex) simplexStack.poll();
|
//System.out.println("Pop = " + simplex);
|
simplex.subdivide(this);
|
}
|
}
|
|
void simplexcube0(double cx, double cy, double cz,
|
double[] cube, int pa, int pb, int pc)
|
{
|
recurseSimplex(cx, cy, cz,
|
cube[pa * 3], cube[pa * 3 + 1], cube[pa * 3 + 2],
|
cube[pb * 3], cube[pb * 3 + 1], cube[pb * 3 + 2],
|
cube[pc * 3], cube[pc * 3 + 1], cube[pc * 3 + 2],
|
1);
|
}
|
|
Simplex SimplexCube(Simplex.Point c, // double cx, double cy, double cz,
|
double[] cube, int pa, int pb, int pc)
|
{
|
return new Simplex(c, // x,cy,cz,
|
cube3[pa], // *3], cube[pa*3 + 1], cube[pa*3 + 2],
|
cube3[pb], // *3], cube[pb*3 + 1], cube[pb*3 + 2],
|
cube3[pc], // *3], cube[pc*3 + 1], cube[pc*3 + 2],
|
0);
|
}
|
|
void recurseSimplex(double ax, double ay, double az,
|
double bx, double by, double bz,
|
double cx, double cy, double cz,
|
double dx, double dy, double dz,
|
int depth)
|
{
|
//Applet3D.tracein("recurseSimplex", "(" + ax + ", " + ay + ", " + az +
|
// "), (" + bx + ", " + by + ", " + bz +
|
// "), (" + cx + ", " + cy + ", " + cz +
|
// "), (" + dx + ", " + dy + ", " + dz + ")");
|
//if (depth >= cellSize - 3) // || depth >= cellSize)
|
{
|
inside[0] = implicit.inside(ax, ay, az, false); // true);
|
inside[1] = implicit.inside(bx, by, bz, false); // true);
|
inside[2] = implicit.inside(cx, cy, cz, false); // true);
|
inside[3] = implicit.inside(dx, dy, dz, false); // true);
|
|
boolean tryit = true;
|
//if (false) // depth >= cellSize - 3)
|
{
|
if (inside[0] && inside[1] && inside[2] && inside[3])
|
{
|
tryit = false;
|
}
|
if (!inside[0] && !inside[1] && !inside[2] && !inside[3])
|
{
|
tryit = false;
|
}
|
}
|
|
if (tryit && acceptSimplex(depth >= cellSize, ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz))
|
{
|
//Applet3D.traceout();
|
return;
|
}
|
|
if (!tryit && depth >= cellSize2)
|
{
|
if (DEBUG && inside[0])
|
{
|
pp.x = ax;
|
pp.y = ay;
|
pp.z = az;
|
qq.x = bx;
|
qq.y = by;
|
qq.z = bz;
|
rr.x = cx;
|
rr.y = cy;
|
rr.z = cz;
|
ss.x = dx;
|
ss.y = dy;
|
ss.z = dz;
|
double refx = (ax + bx + cx + dx) / 4;
|
double refy = (ay + by + cy + dy) / 4;
|
double refz = (az + bz + cz + dz) / 4;
|
appendTriangleRef(pp, qq, rr, refx, refy, refz, true);
|
appendTriangleRef(pp, qq, ss, refx, refy, refz, true);
|
appendTriangleRef(pp, rr, ss, refx, refy, refz, true);
|
appendTriangleRef(qq, rr, ss, refx, refy, refz, true);
|
}
|
|
//Applet3D.traceout();
|
return;
|
}
|
}
|
|
// Subdivide
|
double abx = (ax + bx) / 2;
|
double aby = (ay + by) / 2;
|
double abz = (az + bz) / 2;
|
double acx = (ax + cx) / 2;
|
double acy = (ay + cy) / 2;
|
double acz = (az + cz) / 2;
|
double adx = (ax + dx) / 2;
|
double ady = (ay + dy) / 2;
|
double adz = (az + dz) / 2;
|
double bcx = (bx + cx) / 2;
|
double bcy = (by + cy) / 2;
|
double bcz = (bz + cz) / 2;
|
double cdx = (cx + dx) / 2;
|
double cdy = (cy + dy) / 2;
|
double cdz = (cz + dz) / 2;
|
double dbx = (dx + bx) / 2;
|
double dby = (dy + by) / 2;
|
double dbz = (dz + bz) / 2;
|
|
//double mx = (ax + bx + cx + dx) / 4;
|
//double my = (ay + by + cy + dy) / 4;
|
//double mz = (az + bz + cz + dz) / 4;
|
|
recurseSimplex(ax, ay, az,
|
abx, aby, abz,
|
acx, acy, acz,
|
adx, ady, adz, depth + 1);
|
recurseSimplex(bx, by, bz,
|
abx, aby, abz,
|
bcx, bcy, bcz,
|
dbx, dby, dbz, depth + 1);
|
recurseSimplex(cx, cy, cz,
|
acx, acy, acz,
|
bcx, bcy, bcz,
|
cdx, cdy, cdz, depth + 1);
|
recurseSimplex(dx, dy, dz,
|
adx, ady, adz,
|
cdx, cdy, cdz,
|
dbx, dby, dbz, depth + 1);
|
|
v0.x = abx;
|
v0.y = aby;
|
v0.z = abz;
|
v1.x = cdx;
|
v1.y = cdy;
|
v1.z = cdz;
|
//LA.vecSub(v0,v1, v2);
|
double diag0 = LA.distance2(v0, v1);
|
|
v0.x = acx;
|
v0.y = acy;
|
v0.z = acz;
|
v1.x = dbx;
|
v1.y = dby;
|
v1.z = dbz;
|
//LA.vecSub(v0,v1, v2);
|
double diag1 = LA.distance2(v0, v1);
|
|
v0.x = adx;
|
v0.y = ady;
|
v0.z = adz;
|
v1.x = bcx;
|
v1.y = bcy;
|
v1.z = bcz;
|
//LA.vecSub(v0,v1, v2);
|
double diag2 = LA.distance2(v0, v1);
|
|
int which = 0;
|
double min = diag0;
|
|
if (min > diag1)
|
{
|
min = diag1;
|
which = 1;
|
}
|
|
if (min > diag2)
|
{
|
min = diag2;
|
which = 2;
|
}
|
|
// Central octahedron
|
switch (which) // depth % 3)
|
{
|
case 0:
|
recurseSimplex(abx, aby, abz,
|
cdx, cdy, cdz,
|
bcx, bcy, bcz,
|
dbx, dby, dbz, depth + 1);
|
recurseSimplex(abx, aby, abz,
|
cdx, cdy, cdz,
|
dbx, dby, dbz,
|
adx, ady, adz, depth + 1);
|
recurseSimplex(abx, aby, abz,
|
cdx, cdy, cdz,
|
adx, ady, adz,
|
acx, acy, acz, depth + 1);
|
recurseSimplex(abx, aby, abz,
|
cdx, cdy, cdz,
|
acx, acy, acz,
|
bcx, bcy, bcz, depth + 1);
|
break;
|
case 1:
|
recurseSimplex(acx, acy, acz,
|
dbx, dby, dbz,
|
abx, aby, abz,
|
adx, ady, adz, depth + 1);
|
recurseSimplex(acx, acy, acz,
|
dbx, dby, dbz,
|
adx, ady, adz,
|
cdx, cdy, cdz, depth + 1);
|
recurseSimplex(acx, acy, acz,
|
dbx, dby, dbz,
|
cdx, cdy, cdz,
|
bcx, bcy, bcz, depth + 1);
|
recurseSimplex(acx, acy, acz,
|
dbx, dby, dbz,
|
bcx, bcy, bcz,
|
abx, aby, abz, depth + 1);
|
break;
|
case 2:
|
recurseSimplex(adx, ady, adz,
|
bcx, bcy, bcz,
|
abx, aby, abz,
|
acx, acy, acz, depth + 1);
|
recurseSimplex(adx, ady, adz,
|
bcx, bcy, bcz,
|
acx, acy, acz,
|
cdx, cdy, cdz, depth + 1);
|
recurseSimplex(adx, ady, adz,
|
bcx, bcy, bcz,
|
cdx, cdy, cdz,
|
dbx, dby, dbz, depth + 1);
|
recurseSimplex(adx, ady, adz,
|
bcx, bcy, bcz,
|
dbx, dby, dbz,
|
abx, aby, abz, depth + 1);
|
break;
|
default:
|
}
|
|
/*
|
// Vertex
|
recurseSimplex(mx,my,mz,
|
abx,aby,abz,
|
acx,acy,acz,
|
adx,ady,adz, depth + 1);
|
recurseSimplex(mx,my,mz,
|
abx,aby,abz,
|
bcx,bcy,bcz,
|
dbx,dby,dbz, depth + 1);
|
recurseSimplex(mx,my,mz,
|
acx,acy,acz,
|
bcx,bcy,bcz,
|
cdx,cdy,cdz, depth + 1);
|
recurseSimplex(mx,my,mz,
|
adx,ady,adz,
|
cdx,cdy,cdz,
|
dbx,dby,dbz, depth + 1);
|
// Face
|
recurseSimplex(mx,my,mz,
|
bcx,bcy,bcz,
|
cdx,cdy,cdz,
|
dbx,dby,dbz, depth + 1);
|
recurseSimplex(mx,my,mz,
|
acx,acy,acz,
|
cdx,cdy,cdz,
|
adx,ady,adz, depth + 1);
|
recurseSimplex(mx,my,mz,
|
abx,aby,abz,
|
adx,ady,adz,
|
dbx,dby,dbz, depth + 1);
|
recurseSimplex(mx,my,mz,
|
abx,aby,abz,
|
acx,acy,acz,
|
bcx,bcy,bcz, depth + 1);
|
*/
|
|
//Applet3D.traceout();
|
}
|
|
boolean acceptSimplex(boolean forced, double ax, double ay, double az,
|
double bx, double by, double bz,
|
double cx, double cy, double cz,
|
double dx, double dy, double dz)
|
{
|
assert false;
|
//cVector[] triangle = new cVector[4];
|
|
//Applet3D.tracein("acceptSimplex");
|
int i = 0;
|
|
interindex = 0;
|
|
if (inside[0] ^ inside[1])
|
{
|
triangle[i++] = intersect(ax, ay, az, bx, by, bz, inside[0]);
|
}
|
if (inside[0] ^ inside[2])
|
{
|
triangle[i++] = intersect(ax, ay, az, cx, cy, cz, inside[0]);
|
}
|
if (inside[0] ^ inside[3])
|
{
|
triangle[i++] = intersect(ax, ay, az, dx, dy, dz, inside[0]);
|
}
|
if (inside[1] ^ inside[2])
|
{
|
triangle[i++] = intersect(bx, by, bz, cx, cy, cz, inside[1]);
|
}
|
if (inside[1] ^ inside[3])
|
{
|
triangle[i++] = intersect(bx, by, bz, dx, dy, dz, inside[1]);
|
}
|
if (inside[2] ^ inside[3])
|
{
|
triangle[i++] = intersect(cx, cy, cz, dx, dy, dz, inside[2]);
|
}
|
|
if (i != 3 && i != 4)
|
//new Exception("Must have 3-4 intersections").printStackTrace();
|
{
|
System.out.println("Must have 3-4 intersections: " + i);
|
}
|
|
//if (i == 3) return maxdepth;
|
if (!forced && tolerance == 0) // + 1E-5)
|
{
|
////GraphreeD.traceout();
|
return false;
|
}
|
|
if (i == 4 && !forced)
|
{
|
/*
|
if (!coplanar(triangle[0], triangle[1], triangle[2], triangle[3]))
|
{
|
Applet3D.traceout();
|
return false;
|
}
|
*/
|
|
simplex[0].x = ax;
|
simplex[0].y = ay;
|
simplex[0].z = az;
|
simplex[1].x = bx;
|
simplex[1].y = by;
|
simplex[1].z = bz;
|
simplex[2].x = cx;
|
simplex[2].y = cy;
|
simplex[2].z = cz;
|
simplex[3].x = dx;
|
simplex[3].y = dy;
|
simplex[3].z = dz;
|
|
v0.x = 0;
|
v0.y = 0;
|
v0.z = 0;
|
v1.x = 0;
|
v1.y = 0;
|
v1.z = 0;
|
|
for (int l = 0; l < 4; l++)
|
{
|
if (inside[l])
|
{
|
v0.x += simplex[l].x / 2;
|
v0.y += simplex[l].y / 2;
|
v0.z += simplex[l].z / 2;
|
} else
|
{
|
v1.x += simplex[l].x / 2;
|
v1.y += simplex[l].y / 2;
|
v1.z += simplex[l].z / 2;
|
}
|
}
|
|
LA.vecSub(v0, v1, v2);
|
LA.vecNormalize(v2);
|
|
cVector inter = intersect(v0.x, v0.y, v0.z,
|
v1.x, v1.y, v1.z,
|
true);
|
|
v0.x = (triangle[0].x + triangle[1].x + triangle[2].x + triangle[3].x) / 4;
|
v0.y = (triangle[0].y + triangle[1].y + triangle[2].y + triangle[3].y) / 4;
|
v0.z = (triangle[0].z + triangle[1].z + triangle[2].z + triangle[3].z) / 4;
|
|
/*
|
if (oppositeSide(triangle[0], triangle[1], triangle[2], triangle[3]))
|
{
|
v0.x = (triangle[1].x + triangle[2].x)/2;
|
v0.y = (triangle[1].y + triangle[2].y)/2;
|
v0.z = (triangle[1].z + triangle[2].z)/2;
|
}
|
else if (oppositeSide(triangle[1], triangle[0], triangle[2], triangle[3]))
|
{
|
v0.x = (triangle[0].x + triangle[2].x)/2;
|
v0.y = (triangle[0].y + triangle[2].y)/2;
|
v0.z = (triangle[0].z + triangle[2].z)/2;
|
}
|
else if (oppositeSide(triangle[2], triangle[0], triangle[1], triangle[3]))
|
{
|
v0.x = (triangle[0].x + triangle[1].x)/2;
|
v0.y = (triangle[0].y + triangle[1].y)/2;
|
v0.z = (triangle[0].z + triangle[1].z)/2;
|
}
|
else System.out.println("NO OTHER TRIANGLE");
|
/**/
|
|
//LA.vecSub(v0,v4, v3);
|
//System.out.println("length = " + LA.vecLen(v3));
|
|
LA.vecSub(inter, v0, v1);
|
|
//System.out.println("dot4 = " + Math.abs(LA.vecDot(v1,v2)));
|
|
if (Math.abs(LA.vecDot(v1, v2)) > tolerance) // + 1E-5)
|
{
|
////GraphreeD.traceout();
|
return false;
|
}
|
}
|
|
if (i == 3 && !forced)
|
{
|
int count = 0;
|
|
for (int l = 0; l < 4; l++)
|
{
|
if (inside[l])
|
{
|
count++;
|
}
|
}
|
|
int which;
|
|
if (count == 3) // get false one
|
{
|
for (which = 0; which < 4; which++)
|
{
|
if (!inside[which])
|
{
|
break;
|
}
|
}
|
} else // get true one
|
{
|
if (count != 1)
|
{
|
System.out.println("COUNT != 1");
|
}
|
for (which = 0; which < 4; which++)
|
{
|
if (inside[which])
|
{
|
break;
|
}
|
}
|
}
|
|
simplex[0].x = ax;
|
simplex[0].y = ay;
|
simplex[0].z = az;
|
simplex[1].x = bx;
|
simplex[1].y = by;
|
simplex[1].z = bz;
|
simplex[2].x = cx;
|
simplex[2].y = cy;
|
simplex[2].z = cz;
|
simplex[3].x = dx;
|
simplex[3].y = dy;
|
simplex[3].z = dz;
|
|
cVector vert1 = simplex[(which + 1) % 4];
|
cVector vert2 = simplex[(which + 2) % 4];
|
cVector vert3 = simplex[(which + 3) % 4];
|
|
v2.x = (vert1.x + vert2.x + vert3.x) / 3;
|
v2.y = (vert1.y + vert2.y + vert3.y) / 3;
|
v2.z = (vert1.z + vert2.z + vert3.z) / 3;
|
|
if (implicit.inside(v2.x, v2.y, v2.z, false /*true*/) == inside[which])
|
{
|
////GraphreeD.traceout();
|
return false;
|
}
|
|
cVector inter = intersect(simplex[which].x, simplex[which].y, simplex[which].z,
|
v2.x, v2.y, v2.z,
|
inside[which]);
|
|
LA.vecSub(triangle[0], triangle[1], v0);
|
LA.vecSub(triangle[0], triangle[2], v1);
|
LA.vecCross(v0, v1, v2);
|
LA.vecNormalize(v2);
|
|
v0.x = (triangle[0].x + triangle[1].x + triangle[2].x) / 3;
|
v0.y = (triangle[0].y + triangle[1].y + triangle[2].y) / 3;
|
v0.z = (triangle[0].z + triangle[1].z + triangle[2].z) / 3;
|
|
LA.vecSub(inter, v0, v1);
|
|
//System.out.println("dot3 = " + Math.abs(LA.vecDot(v1,v2)));
|
|
if (Math.abs(LA.vecDot(v1, v2)) > tolerance) // + 1E-5)
|
{
|
////GraphreeD.traceout();
|
return false;
|
}
|
}
|
|
if (!DEBUG)
|
{
|
appendTriangleRef(triangle[0], triangle[1], triangle[2], ax, ay, az, inside[0]);
|
}
|
|
if (!DEBUG && i == 4)
|
{
|
if (oppositeSide(triangle[0], triangle[1], triangle[2], triangle[3]))
|
{
|
appendTriangleRef(triangle[1], triangle[2], triangle[3], ax, ay, az, inside[0]);
|
} else if (oppositeSide(triangle[1], triangle[0], triangle[2], triangle[3]))
|
{
|
appendTriangleRef(triangle[0], triangle[2], triangle[3], ax, ay, az, inside[0]);
|
} else if (oppositeSide(triangle[2], triangle[0], triangle[1], triangle[3]))
|
{
|
appendTriangleRef(triangle[0], triangle[1], triangle[3], ax, ay, az, inside[0]);
|
} else
|
{
|
System.out.println("NO OTHER TRIANGLE");
|
}
|
}
|
|
//Applet3D.traceout();
|
return true;
|
}
|
|
boolean oppositeSide(cVector point, cVector edge1, cVector edge2, cVector ref)
|
{
|
LA.vecSub(point, edge1, v0);
|
LA.vecSub(ref, edge1, v1);
|
LA.vecCross(v0, v1, v2);
|
LA.vecSub(edge2, edge1, v3);
|
LA.vecCross(v2, v3, v4);
|
|
return (LA.vecDot(v0, v4) < 0) ^ (LA.vecDot(v1, v4) < 0);
|
}
|
|
boolean coplanar(cVector pa, cVector pb, cVector pc, cVector pd)
|
{
|
LA.vecSub(pa, pb, v0);
|
LA.vecNormalize(v0);
|
LA.vecSub(pa, pc, v1);
|
LA.vecNormalize(v1);
|
LA.vecCross(v0, v1, v2);
|
LA.vecNormalize(v2);
|
LA.vecSub(pa, pd, v3);
|
|
double dist = Math.abs(LA.vecDot(v2, v3));
|
|
//System.out.println("dist = " + dist);
|
return dist < tolerance;
|
}
|
cVector corners[] = new cVector[12];
|
|
void decompose()
|
{
|
/*
|
boolean clockwise = false;
|
int nCorners = 0;
|
int edge = 0;
|
int first = -1;
|
int nLoops = 0;
|
label0:
|
do
|
{
|
do
|
{
|
if (nCorners > 12)
|
{
|
System.out.println("nCorners > 12");
|
break;
|
}
|
if (nLoops > 12)
|
{
|
System.out.println("nLoops > 12");
|
break;
|
}
|
int p = decompTable[edge][0];
|
int q = decompTable[edge][1];
|
if (inside8[p] == inside8[q])
|
continue label0;
|
corners[nCorners] = intersect(xc8[p], yc8[p], zc8[p], xc8[q], yc8[q], zc8[q], inside8[p]);
|
if (nCorners == 0)
|
{
|
first = edge;
|
clockwise = inside8[p];
|
}
|
nCorners++;
|
edge = decompTable[edge][3];
|
} while (edge != first);
|
break;
|
} while (nCorners != 0 ? (edge = decompTable[edge][2]) != first : ++edge != 24);
|
if (nCorners < 3)
|
return;
|
if (clockwise)
|
{
|
int p = 0;
|
int q = 1;
|
for (int r = 2; r < nCorners; r++)
|
{
|
appendTriangle(corners[p], corners[r], corners[q]);
|
q++;
|
}
|
} else
|
{
|
int p = nCorners - 1;
|
int q = p - 1;
|
for (int r = q - 1; r >= 0; r--)
|
{
|
appendTriangle(corners[p], corners[r], corners[q]);
|
q--;
|
}
|
}
|
*/
|
}
|
Vector interlist = new Vector();
|
int interindex;
|
|
Vertex intersect(double x1, double y1, double z1, double x2, double y2, double z2, boolean pIn)
|
{
|
if (!pIn)
|
{
|
double temp = x1;
|
x1 = x2;
|
x2 = temp;
|
temp = y1;
|
y1 = y2;
|
y2 = temp;
|
temp = z1;
|
z1 = z2;
|
z2 = temp;
|
}
|
Vertex result = (Vertex) interlist.get(interindex++); // new cVector();
|
do
|
{
|
result.x = 0.5 * (x1 + x2);
|
result.y = 0.5 * (y1 + y2);
|
result.z = 0.5 * (z1 + z2);
|
|
if (Math.abs(x1 - x2) + Math.abs(y1 - y2) + Math.abs(z1 - z2) < 0.001)
|
{
|
return result;
|
}
|
|
if (implicit.inside(result.x, result.y, result.z, false)) // true))
|
{
|
x1 = result.x;
|
y1 = result.y;
|
z1 = result.z;
|
} else
|
{
|
x2 = result.x;
|
y2 = result.y;
|
z2 = result.z;
|
}
|
} while (true);
|
}
|
|
void appendTriangleRef(Vertex p, Vertex q, Vertex r, double refx, double refy, double refz, boolean insideref)
|
{
|
ref.x = refx;
|
ref.y = refy;
|
ref.z = refz;
|
|
LA.vecSub(p, q, v0);
|
LA.vecSub(p, r, v1);
|
LA.vecCross(v0, v1, v2);
|
|
LA.vecSub(p, ref, v1);
|
|
if ((LA.vecDot(v1, v2) < 0) ^ insideref)
|
{
|
appendTriangle(p, q, r);
|
} else
|
{
|
appendTriangle(p, r, q);
|
}
|
}
|
Vertex vert = new Vertex(true);
|
|
public void appendTriangle(Vertex p, Vertex q, Vertex r)
|
{
|
//Applet3D.tracein("appendTriangle", p + "; " + q + "; " + r);
|
int qx;
|
int rx;
|
int px; // = qx = rx = -1;
|
/*
|
for (int i=0; i != bRep.vertices.size() && (px == -1 || qx == -1 || rx == -1); i++)
|
{
|
Vertex vert = (Vertex)bRep.vertices.elementAt(i);
|
if (px == -1 && Math.abs(p.x - vert.x) + Math.abs(p.y - vert.y) + Math.abs(p.z - vert.z) < 0.1)
|
px = i;
|
if (qx == -1 && Math.abs(q.x - vert.x) + Math.abs(q.y - vert.y) + Math.abs(q.z - vert.z) < 0.1)
|
qx = i;
|
if (rx == -1 && Math.abs(r.x - vert.x) + Math.abs(r.y - vert.y) + Math.abs(r.z - vert.z) < 0.1)
|
rx = i;
|
}
|
/**/
|
//if (px == -1)
|
{
|
//Vertex vert = new Vertex();
|
//vert.pos = new cVector();
|
LA.vecCopy(p, vert/*.pos*/);
|
LA.vecCopy(p.norm, vert.norm);
|
Vertex in = bRep.GetCache(vert);
|
if (in != null)
|
{
|
px = in.index;
|
} else
|
{
|
Vertex vert2 = new Vertex(true);
|
LA.vecCopy(vert/*.pos*/, vert2/*.pos*/);
|
LA.vecCopy(vert.norm, vert2.norm);
|
px = bRep.VertexCount();
|
vert2.index = px;
|
//bRep.AddVertex(vert2);
|
bRep.Remember(vert2);
|
}
|
}
|
//if (qx == -1)
|
{
|
//Vertex vert = new Vertex();
|
//vert.pos = new cVector();
|
LA.vecCopy(q, vert/*.pos*/);
|
LA.vecCopy(q.norm, vert.norm);
|
Vertex in = bRep.GetCache(vert);
|
if (in != null)
|
{
|
qx = in.index;
|
} else
|
{
|
Vertex vert2 = new Vertex(true);
|
LA.vecCopy(vert/*.pos*/, vert2/*.pos*/);
|
LA.vecCopy(vert.norm, vert2.norm);
|
qx = bRep.VertexCount(); // vertices.size();
|
vert2.index = qx;
|
//bRep.AddVertex(vert2);
|
bRep.Remember(vert2); // vertextable.put(vert2, vert2);
|
}
|
}
|
//if (rx == -1)
|
{
|
//Vertex vert = new Vertex();
|
//vert.pos = new cVector();
|
LA.vecCopy(r, vert/*.pos*/);
|
LA.vecCopy(r.norm, vert.norm);
|
Vertex in = bRep.GetCache(vert);
|
if (in != null)
|
{
|
rx = in.index;
|
} else
|
{
|
Vertex vert2 = new Vertex(true);
|
LA.vecCopy(vert/*.pos*/, vert2/*.pos*/);
|
LA.vecCopy(vert.norm, vert2.norm);
|
rx = bRep.VertexCount();
|
vert2.index = rx;
|
//bRep.AddVertex(vert2);
|
bRep.Remember(vert2);
|
}
|
}
|
bRep.AddFace(px, qx, rx);
|
/*
|
Face face = new Face();
|
face.p = px;
|
face.q = qx;
|
face.r = rx;
|
bRep.faces.addElement(face);
|
*/
|
|
//Applet3D.traceout();
|
}
|
Object3D implicit;
|
double cellSize;
|
double cellSize2;
|
double tolerance;
|
BoundaryRep bRep;
|
int[] nCells;
|
cVector minima;
|
cVector maxima;
|
static Vertex[] triangle = new Vertex[4];
|
static cVector[] simplex = new cVector[4];
|
|
static
|
{
|
for (int i = 0; i < 4; i++)
|
{
|
simplex[i] = new cVector();
|
}
|
}
|
static double[] cube = new double[24];
|
static Simplex.Point[] cube3 = new Simplex.Point[8];
|
private static cVector ref = new cVector();
|
private static cVector v0 = new cVector();
|
private static cVector v1 = new cVector();
|
private static cVector v2 = new cVector();
|
private static cVector v3 = new cVector();
|
private static cVector v4 = new cVector();
|
private static Vertex pp = new Vertex();
|
private static Vertex qq = new Vertex();
|
private static Vertex rr = new Vertex();
|
private static Vertex ss = new Vertex();
|
private static final double epsilon = 0.1;
|
private static final int maxCells = 500;
|
private static double xc8[] = new double[8];
|
private static double yc8[] = new double[8];
|
private static double zc8[] = new double[8];
|
private static boolean inside8[] = new boolean[8];
|
private static boolean inside[] = new boolean[4];
|
private static final int P = 0;
|
private static final int Q = 1;
|
private static final int Fail = 2;
|
private static final int Succeed = 3;
|
private static final int decompTable[][] = {
|
{
|
0, 2, 1, 16
|
}, {
|
2, 3, 2, 12
|
}, {
|
3, 1, 3, 21
|
}, {
|
1, 0, 0, 9
|
}, {
|
4, 5, 5, 11
|
}, {
|
5, 7, 6, 23
|
}, {
|
7, 6, 7, 14
|
}, {
|
6, 4, 4, 18
|
}, {
|
0, 1, 9, 0
|
}, {
|
1, 5, 10, 20
|
}, {
|
5, 4, 11, 5
|
}, {
|
4, 0, 8, 17
|
}, {
|
2, 6, 13, 19
|
}, {
|
6, 7, 14, 7
|
}, {
|
7, 3, 15, 22
|
}, {
|
3, 2, 12, 2
|
}, {
|
0, 4, 17, 8
|
}, {
|
4, 6, 18, 4
|
}, {
|
6, 2, 19, 13
|
}, {
|
2, 0, 16, 1
|
}, {
|
1, 3, 21, 3
|
}, {
|
3, 7, 22, 15
|
}, {
|
7, 5, 23, 6
|
}, {
|
5, 1, 20, 10
|
}
|
};
|
}
|