use of cbit.vcell.geometry.surface.Node in project vcell by virtualcell.
the class FastMarchingMethodHA method main.
public static void main(String[] args) {
int numX = 2;
int numY = 2;
int numZ = 5;
int numItems = numX * numY * numZ;
double[] distanceMap = new double[numItems];
Arrays.fill(distanceMap, MAX_NUMBER);
// initial condition (exact distances from origin)
distanceMap[0] = 0;
distanceMap[1] = 1;
distanceMap[2] = 1;
// sqrt(2) - diagonal of a square
distanceMap[3] = 1.4142135;
distanceMap[4] = 1;
distanceMap[5] = 1.4142135;
distanceMap[6] = 1.4142135;
// sqrt(3) - diagonal of a cube
distanceMap[7] = 1.7320508;
// ----- next points distances for the above initial conditions
// FMM results vs. FMMHA results vs. exact computed results:
// 8: 2.000000 2.000000 2.000000
// 9: 2.350700 (0.12) 2.204818 (0.03) 2.236067 sqrt(5)
// 10: 2.350700 2.204818 2.236067
// 11: 2.642763 (0.20) 2.459807 (0.01) 2.449489 sqrt(6)
// 12: 3.000000 2.999999 3.000000
// 13: 3.303524 (0.14) 3.129413 (0.04) 3.162277 sqrt(10)
// 14: 3.303524 3.129413 3.162277 sqrt(10)
// 15: 3.569388 (0.25) 3.339079 (0.02) 3.316624 sqrt(2+9)
FastMarchingMethodHA fmm = new FastMarchingMethodHA(numX, numY, numZ, distanceMap, null);
System.out.println("Verifying indexes manipulation; index = x + y*numX + z*numX*numY");
int index = 0;
for (int z = 0; z < numZ; z++) {
for (int y = 0; y < numY; y++) {
for (int x = 0; x < numX; x++) {
index = x + y * numX + z * numX * numY;
System.out.println(x + ", " + y + ", " + z + ": " + index + " ");
System.out.println(fmm.getX(index) + ", " + fmm.getY(index) + ", " + fmm.getZ(index));
}
}
}
System.out.println("x, y, z: index");
fmm.march();
System.out.println("");
System.out.println(" -------------------- TEST 1 - accuracy test ----------------------- ");
long length = fmm.numX * fmm.numY * fmm.numZ;
for (index = 0; index < length; index++) {
System.out.println(index + ": " + distanceMap[index]);
}
System.out.println("");
System.out.println(" -------------------- TEST 2 - large array ----------------------- ");
numX = 100;
numY = 100;
numZ = 100;
numItems = numX * numY * numZ;
distanceMap = new double[numItems];
Arrays.fill(distanceMap, MAX_NUMBER);
// initial condition (a small cylinder) at 20, 20, 20
int x = 50;
int y = 50;
int z = 50;
int i = x + y * numX + z * numX * numY;
distanceMap[i] = 0;
distanceMap[i + 1] = 0;
distanceMap[i + 2] = 0;
// the tips
distanceMap[i - 1] = 1;
distanceMap[i + 3] = 1;
// closest neighbors on XZ plane
i = x + (y + 1) * numX + z * numX * numY;
distanceMap[i] = 0;
distanceMap[i + 1] = 1;
distanceMap[i + 2] = 1;
i = x + (y - 1) * numX + z * numX * numY;
distanceMap[i] = 0;
distanceMap[i + 1] = 1;
distanceMap[i + 2] = 1;
// closest neighbors on XY plane
i = x + y * numX + (z + 1) * numX * numY;
distanceMap[i] = 0;
distanceMap[i + 1] = 1;
distanceMap[i + 2] = 1;
i = x + y * numX + (z - 1) * numX * numY;
distanceMap[i] = 0;
distanceMap[i + 1] = 1;
distanceMap[i + 2] = 1;
fmm = new FastMarchingMethodHA(numX, numY, numZ, distanceMap, null);
long t1 = System.currentTimeMillis();
fmm.march();
long t2 = System.currentTimeMillis();
System.out.println("---------- " + (int) ((t2 - t1) / 1000) + " seconds ----------");
System.out.println("");
System.out.println(" -------------------- TEST 3 - compare accuracy ----------------------- ");
Vect3d p = null;
double d1 = 0;
numX = 100;
numY = 100;
numZ = 100;
numItems = numX * numY * numZ;
distanceMap = new double[numItems];
Arrays.fill(distanceMap, MAX_NUMBER);
Vect3d A = new Vect3d(0, 0, 0);
Vect3d B = new Vect3d(1, 0, 0);
Vect3d C = new Vect3d(0, 1, 0);
i = (int) (A.getX() + A.getY() * numX + A.getZ() * numX * numY);
distanceMap[i] = 0;
i = (int) (B.getX() + B.getY() * numX + B.getZ() * numX * numY);
distanceMap[i] = 0;
i = (int) (C.getX() + C.getY() * numX + C.getZ() * numX * numY);
distanceMap[i] = 0;
fmm = new FastMarchingMethodHA(numX, numY, numZ, distanceMap, null);
fmm.march();
final int numIterations = 500000;
double errorThreshold = 0.51;
int errorCount = 0;
Random rand = new Random();
try {
BufferedWriter out = new BufferedWriter(new FileWriter("c:\\TEMP\\FFM.3D"));
out.write("x y z value\n");
for (int j = 0; j < numIterations; j++) {
x = (int) (rand.nextDouble() * 100);
y = (int) (rand.nextDouble() * 100);
z = (int) (rand.nextDouble() * 100);
i = x + y * numX + z * numX * numY;
p = new Vect3d(x, y, z);
d1 = DistanceMapGenerator.distanceToTriangle3d(p, A, B, C);
double delta = Math.abs(d1 - distanceMap[i]);
String line = new String(x + " " + y + " " + z + " " + (int) (delta * 100) + "\n");
out.write(line);
if (delta > errorThreshold) {
System.out.println(x + ", " + y + ", " + z + " - delta: " + delta);
errorCount++;
}
}
out.close();
System.out.println("Delta above threshold " + errorThreshold + " occured in " + errorCount + " cases out of " + numIterations);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("A few random examples: ffm distance vs. exact distance");
for (int j = 0; j < 5; j++) {
x = (int) (1 + rand.nextDouble() * 98);
y = (int) (1 + rand.nextDouble() * 98);
z = (int) (1 + rand.nextDouble() * 98);
i = x + y * numX + z * numX * numY;
p = new Vect3d(x, y, z);
d1 = DistanceMapGenerator.distanceToTriangle3d(p, A, B, C);
System.out.println(x + ", " + y + ", " + z + " - ffm dist: " + distanceMap[i] + ", exact dist: " + d1);
}
System.out.println("");
System.out.println(" -------------------- TEST 4 - negative entries ----------------------- ");
p = null;
d1 = 0;
numX = 10;
numY = 10;
numZ = 10;
numItems = numX * numY * numZ;
distanceMap = new double[numItems];
Arrays.fill(distanceMap, MAX_NUMBER);
Node AA = new Node(0.501, 0.5, 0.5);
Node BB = new Node(0.5, 0.501, 0.5);
Node CC = new Node(0.5, 0.5, 0.501);
A = new Vect3d(AA);
B = new Vect3d(BB);
C = new Vect3d(CC);
distanceMap[0] = -0.86602540378443864676372317075294;
distanceMap[1] = 0.86602540378443864676372317075294;
distanceMap[10] = 0.86602540378443864676372317075294;
distanceMap[11] = 0.86602540378443864676372317075294;
distanceMap[100] = 0.86602540378443864676372317075294;
distanceMap[101] = 0.86602540378443864676372317075294;
distanceMap[110] = 0.86602540378443864676372317075294;
distanceMap[111] = 0.86602540378443864676372317075294;
fmm = new FastMarchingMethodHA(numX, numY, numZ, distanceMap, null);
fmm.march();
x = 5;
y = 5;
z = 5;
i = x + y * numX + z * numX * numY;
p = new Vect3d(x, y, z);
Node pp = new Node(x, y, z);
d1 = DistanceMapGenerator.distanceToTriangle3d(p, A, B, C);
double d2 = DistanceMapGenerator.distanceToTriangleExperimental(pp, AA, BB, CC, "c:\\TEMP\\triangle.3D");
System.out.println(x + ", " + y + ", " + z + " - ffm dist: " + distanceMap[i] + ", exact dist: " + d1 + ", exper dist: " + d2);
x = 2;
y = 1;
z = 0;
i = x + y * numX + z * numX * numY;
p = new Vect3d(x, y, z);
pp = new Node(x, y, z);
d1 = DistanceMapGenerator.distanceToTriangle3d(p, A, B, C);
d2 = DistanceMapGenerator.distanceToTriangleExperimental(pp, AA, BB, CC, "c:\\TEMP\\triangle.3D");
System.out.println(x + ", " + y + ", " + z + " - ffm dist: " + distanceMap[i] + ", exact dist: " + d1 + ", exper dist: " + d2);
System.out.println("");
System.out.println(" -------------------- TEST 5 ----------------------- ");
p = null;
d1 = 0;
numX = 10;
numY = 10;
numZ = 10;
numItems = numX * numY * numZ;
distanceMap = new double[numItems];
Arrays.fill(distanceMap, MAX_NUMBER);
AA = new Node(0.01, 0, 0);
BB = new Node(0, 0.01, 0);
CC = new Node(0, 0, 0.01);
A = new Vect3d(AA);
B = new Vect3d(BB);
C = new Vect3d(CC);
distanceMap[0] = 0;
distanceMap[1] = 1;
distanceMap[10] = 1;
distanceMap[11] = 1.4142135623730950488016887242097;
distanceMap[100] = 1;
distanceMap[101] = 1.4142135623730950488016887242097;
distanceMap[110] = 1.4142135623730950488016887242097;
distanceMap[111] = 1.7320508075688772935274463415059;
fmm = new FastMarchingMethodHA(numX, numY, numZ, distanceMap, null);
fmm.march();
x = 5;
y = 5;
z = 5;
i = x + y * numX + z * numX * numY;
p = new Vect3d(x, y, z);
pp = new Node(x, y, z);
d1 = DistanceMapGenerator.distanceToTriangle3d(p, A, B, C);
d2 = DistanceMapGenerator.distanceToTriangleExperimental(pp, AA, BB, CC, "c:\\TEMP\\triangle.3D");
System.out.println(x + ", " + y + ", " + z + " - ffm dist: " + distanceMap[i] + ", exact dist: " + d1 + ", exper dist: " + d2);
x = 2;
y = 1;
z = 0;
i = x + y * numX + z * numX * numY;
p = new Vect3d(x, y, z);
pp = new Node(x, y, z);
d1 = DistanceMapGenerator.distanceToTriangle3d(p, A, B, C);
d2 = DistanceMapGenerator.distanceToTriangleExperimental(pp, AA, BB, CC, "c:\\TEMP\\triangle.3D");
System.out.println(x + ", " + y + ", " + z + " - ffm dist: " + distanceMap[i] + ", exact dist: " + d1 + ", exper dist: " + d2);
System.out.println("");
System.out.println(" -------------------- TEST 6 - narrow vertical column ---------------------- ");
p = null;
d1 = 0;
numX = 2;
numY = 2;
numZ = 10;
numItems = numX * numY * numZ;
distanceMap = new double[numItems];
Arrays.fill(distanceMap, MAX_NUMBER);
distanceMap[0] = -0.3;
distanceMap[1] = -0.3;
distanceMap[2] = -0.3;
distanceMap[3] = -0.3;
distanceMap[4] = 0.7;
distanceMap[5] = 0.7;
distanceMap[6] = 0.7;
distanceMap[7] = 0.7;
fmm = new FastMarchingMethodHA(numX, numY, numZ, distanceMap, null);
fmm.march();
for (int j = 8; j < numItems; j++) {
System.out.println(j + ": " + distanceMap[j]);
}
System.out.println("");
System.out.println(" -------------------- TEST 7 - 2D test, numZ must be 1 ---------------------- ");
p = null;
d1 = 0;
numX = 500;
numY = 500;
numZ = 1;
numItems = numX * numY * numZ;
distanceMap = new double[numItems];
Arrays.fill(distanceMap, MAX_NUMBER);
x = 0;
y = 0;
double radius = 200;
for (int alpha = 0; alpha < 360; alpha++) {
double rad = Math.PI * (double) alpha / 180.0;
x = (int) (250.0 + radius * Math.cos(rad));
y = (int) (250.0 + radius * Math.sin(rad));
i = x + y * numX;
distanceMap[i] = 0;
}
try {
// save some points in a VisIt compatible format
BufferedWriter out = new BufferedWriter(new FileWriter("c:\\TEMP\\FFM2D1" + ".3D"));
out.write("x y z value\n");
for (int j = 0; j < distanceMap.length; j++) {
x = DistanceMapGenerator.getX(j, numX, numY);
y = DistanceMapGenerator.getY(j, numX, numY);
z = DistanceMapGenerator.getZ(j, numX, numY);
if (distanceMap[j] < MAX_NUMBER) {
out.write(x + " " + y + " " + z + " " + (int) (distanceMap[j] * 10) + "\n");
}
}
out.close();
} catch (IOException e) {
}
fmm = new FastMarchingMethodHA(numX, numY, numZ, distanceMap, null);
fmm.march();
try {
// save some points in a VisIt compatible format
BufferedWriter out = new BufferedWriter(new FileWriter("c:\\TEMP\\FFM2D2" + ".3D"));
out.write("x y z value\n");
for (int j = 0; j < distanceMap.length; j++) {
x = DistanceMapGenerator.getX(j, numX, numY);
y = DistanceMapGenerator.getY(j, numX, numY);
z = DistanceMapGenerator.getZ(j, numX, numY);
if (distanceMap[j] < MAX_NUMBER) {
out.write(x + " " + y + " " + z + " " + (int) (distanceMap[j] * 10) + "\n");
}
}
out.close();
} catch (IOException e) {
}
System.out.println("");
System.out.println(" -------------------- TEST 8 - anisotropic ---------------------- ");
numX = 2;
numY = 2;
numZ = 5;
numItems = numX * numY * numZ;
distanceMap = new double[numItems];
Arrays.fill(distanceMap, MAX_NUMBER);
// initial condition (exact distances from origin)
distanceMap[0] = 0;
distanceMap[1] = 1;
distanceMap[2] = 1;
// sqrt(2) - diagonal of a square
distanceMap[3] = 1.4142135623730950488016887242097;
distanceMap[4] = 2;
// sqrt(5)
distanceMap[5] = 2.2360679774997896964091736687313;
distanceMap[6] = 2.2360679774997896964091736687313;
// sqrt(6)
distanceMap[7] = 2.4494897427831780981972840747059;
// ----- next points distances for the above initial conditions
// FMM-plain FMM-HA exact computed:
// 8: 4.00000000 N/A 4.00000000
// 9: 4.19691079 4.12310562 // sqrt(17)
// 10:
// 11: 4.38072927 4.24264068
// 12: 6.00000000 6.00000000
// 13: 6.16836145 6.08276253 // sqrt(37)
// 14:
// 15: 6.32866014 6.16441400 // sqrt(16+2)
fmm = new FastMarchingMethodHA(numX, numY, numZ, 1, 1, 2, distanceMap, null);
System.out.println("Verifying indexes manipulation; index = x + y*numX + z*numX*numY");
fmm.march();
length = fmm.numX * fmm.numY * fmm.numZ;
for (index = 0; index < length; index++) {
System.out.println(index + ": " + distanceMap[index]);
}
System.out.println("");
System.out.println(" -------------------- TEST 9 - LONG test ---------------------- ");
numX = 300;
numY = 300;
numZ = 300;
numItems = numX * numY * numZ;
distanceMap = new double[numItems];
Arrays.fill(distanceMap, MAX_NUMBER);
distanceMap[0] = 0;
distanceMap[1] = 1;
distanceMap[300] = 1;
distanceMap[301] = 1.4142135623730950488016887242097;
distanceMap[90000] = 1;
distanceMap[90001] = 1.4142135623730950488016887242097;
distanceMap[90300] = 1.4142135623730950488016887242097;
distanceMap[90301] = 1.7320508075688772935274463415059;
fmm = new FastMarchingMethodHA(numX, numY, numZ, distanceMap, null);
fmm.march();
System.out.println("Done");
}
use of cbit.vcell.geometry.surface.Node in project vcell by virtualcell.
the class SmoldynFileWriter method writeSurfaces.
private void writeSurfaces() throws SolverException, ImageException, PropertyVetoException, GeometryException, ExpressionException {
GeometrySurfaceDescription geometrySurfaceDescription = resampledGeometry.getGeometrySurfaceDescription();
SurfaceClass[] surfaceClasses = geometrySurfaceDescription.getSurfaceClasses();
GeometrySpec geometrySpec = resampledGeometry.getGeometrySpec();
SubVolume[] surfaceGeometrySubVolumes = geometrySpec.getSubVolumes();
GeometricRegion[] AllGeometricRegions = resampledGeometry.getGeometrySurfaceDescription().getGeometricRegions();
ArrayList<SurfaceGeometricRegion> surfaceRegionList = new ArrayList<SurfaceGeometricRegion>();
ArrayList<VolumeGeometricRegion> volumeRegionList = new ArrayList<VolumeGeometricRegion>();
for (GeometricRegion geometricRegion : AllGeometricRegions) {
if (geometricRegion instanceof SurfaceGeometricRegion) {
surfaceRegionList.add((SurfaceGeometricRegion) geometricRegion);
} else if (geometricRegion instanceof VolumeGeometricRegion) {
volumeRegionList.add((VolumeGeometricRegion) geometricRegion);
} else {
throw new SolverException("unsupported geometric region type " + geometricRegion.getClass());
}
}
printWriter.println("# geometry");
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.dim + " " + dimension);
if (bHasNoSurface) {
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_compartment + " " + surfaceGeometrySubVolumes.length);
} else {
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_compartment + " " + (surfaceGeometrySubVolumes.length + 1));
// plus the surface which are bounding walls
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_surface + " " + (surfaceClasses.length + dimension));
}
printWriter.println();
// write boundaries and wall surfaces
writeWallSurfaces();
// for 3D ... smoldyn normal convension is triangle right-hand-rule normal points to the outside compartment subdomain.
if (!bHasNoSurface) {
membraneSubdomainTriangleMap = new HashMap<MembraneSubDomain, ArrayList<TrianglePanel>>();
// write surfaces
printWriter.println("# surfaces");
int triangleGlobalCount = 0;
int membraneIndex = -1;
SurfaceCollection surfaceCollection = geometrySurfaceDescription.getSurfaceCollection();
// pre-allocate collections used repeatedly in following loops; clear before reusing
HashMap<Node, Set<String>> nodeTriMap = new HashMap<>();
ArrayList<TrianglePanel> triList = new ArrayList<TrianglePanel>();
// use a sorted set to ensure neighbors written out is same order for reproducibility
SortedSet<String> neighborsForCurrentNode = new TreeSet<String>();
for (int sci = 0; sci < surfaceClasses.length; sci++) {
nodeTriMap.clear();
triList.clear();
int triLocalCount = 0;
SurfaceClass surfaceClass = surfaceClasses[sci];
GeometricRegion[] geometricRegions = geometrySurfaceDescription.getGeometricRegions(surfaceClass);
for (GeometricRegion gr : geometricRegions) {
SurfaceGeometricRegion sgr = (SurfaceGeometricRegion) gr;
VolumeGeometricRegion volRegion0 = (VolumeGeometricRegion) sgr.getAdjacentGeometricRegions()[0];
VolumeGeometricRegion volRegion1 = (VolumeGeometricRegion) sgr.getAdjacentGeometricRegions()[1];
SubVolume subVolume0 = volRegion0.getSubVolume();
SubVolume subVolume1 = volRegion1.getSubVolume();
CompartmentSubDomain compart0 = mathDesc.getCompartmentSubDomain(subVolume0.getName());
CompartmentSubDomain compart1 = mathDesc.getCompartmentSubDomain(subVolume1.getName());
MembraneSubDomain membraneSubDomain = mathDesc.getMembraneSubDomain(compart0, compart1);
if (membraneSubDomain == null) {
throw new SolverException(VCellErrorMessages.getSmoldynUnexpectedSurface(compart0, compart1));
}
int exteriorRegionID = volRegion0.getRegionID();
int interiorRegionID = volRegion1.getRegionID();
if (membraneSubDomain.getInsideCompartment() == compart0) {
exteriorRegionID = volRegion1.getRegionID();
interiorRegionID = volRegion0.getRegionID();
}
for (int j = 0; j < surfaceCollection.getSurfaceCount(); j++) {
Surface surface = surfaceCollection.getSurfaces(j);
if ((surface.getInteriorRegionIndex() == exteriorRegionID && surface.getExteriorRegionIndex() == interiorRegionID) || (surface.getInteriorRegionIndex() == interiorRegionID && surface.getExteriorRegionIndex() == exteriorRegionID)) {
// Polygon polygon = surface.getPolygons(k);
for (Polygon polygon : surface) {
if (polygonMembaneElementMap != null) {
membraneIndex = polygonMembaneElementMap.get(polygon).getMembraneIndex();
}
Node[] nodes = polygon.getNodes();
if (dimension == 2) {
// ignore z
Vect3d unitNormal = new Vect3d();
polygon.getUnitNormal(unitNormal);
unitNormal.set(unitNormal.getX(), unitNormal.getY(), 0);
int point0 = 0;
Vect3d v0 = new Vect3d(nodes[point0].getX(), nodes[point0].getY(), 0);
int point1 = 1;
Vect3d v1 = null;
for (point1 = 1; point1 < nodes.length; point1++) {
if (v0.getX() != nodes[point1].getX() || v0.getY() != nodes[point1].getY()) {
v1 = new Vect3d(nodes[point1].getX(), nodes[point1].getY(), 0);
break;
}
}
if (v1 == null) {
throw new RuntimeException("failed to generate surface");
}
Vect3d v01 = Vect3d.sub(v1, v0);
Vect3d unit01n = v01.cross(unitNormal);
unit01n.unit();
if (Math.abs(unit01n.getZ() - 1.0) < 1e-6) {
// v0 to v1 opposes vcell surface normal. it's already flipped.
Triangle triangle;
if (surface.getInteriorRegionIndex() == interiorRegionID) {
// we have to flipped it back
triangle = new Triangle(nodes[point1], nodes[point0], null);
} else {
triangle = new Triangle(nodes[point0], nodes[point1], null);
}
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle));
} else if (Math.abs(unit01n.getZ() + 1.0) < 1e-6) {
// v0 to v1 is in direction of vcell surface normal.
Triangle triangle;
if (surface.getInteriorRegionIndex() == interiorRegionID) {
triangle = new Triangle(nodes[point0], nodes[point1], null);
} else {
triangle = new Triangle(nodes[point1], nodes[point0], null);
}
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle));
} else {
throw new RuntimeException("failed to generate surface");
}
} else if (dimension == 3) {
Triangle triangle1;
Triangle triangle2;
if (surface.getInteriorRegionIndex() == interiorRegionID) {
// interior
triangle1 = new Triangle(nodes[0], nodes[1], nodes[2]);
triangle2 = new Triangle(nodes[0], nodes[2], nodes[3]);
} else {
triangle1 = new Triangle(nodes[2], nodes[1], nodes[0]);
triangle2 = new Triangle(nodes[3], nodes[2], nodes[0]);
}
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle1));
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle2));
}
}
}
}
}
// add triangles to node hash
for (TrianglePanel triPanel : triList) {
for (Node node : triPanel.triangle.getNodes()) {
if (node == null) {
continue;
}
Set<String> triNameSet = nodeTriMap.get(node);
if (triNameSet == null) {
triNameSet = new HashSet<String>();
nodeTriMap.put(node, triNameSet);
}
triNameSet.add(triPanel.name);
}
}
SubVolume[] adjacentSubvolums = surfaceClass.getAdjacentSubvolumes().toArray(new SubVolume[0]);
CompartmentSubDomain csd0 = simulation.getMathDescription().getCompartmentSubDomain(adjacentSubvolums[0].getName());
CompartmentSubDomain csd1 = simulation.getMathDescription().getCompartmentSubDomain(adjacentSubvolums[1].getName());
MembraneSubDomain membraneSubDomain = simulation.getMathDescription().getMembraneSubDomain(csd0, csd1);
membraneSubdomainTriangleMap.put(membraneSubDomain, triList);
final boolean initialMoleculesOnMembrane = (closestTriangles != null);
if (initialMoleculesOnMembrane) {
findClosestTriangles(membraneSubDomain, triList);
}
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.start_surface + " " + surfaceClass.getName());
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.action + " " + SmoldynVCellMapper.SmoldynKeyword.all + "(" + SmoldynVCellMapper.SmoldynKeyword.all + ") " + SmoldynVCellMapper.SmoldynKeyword.both + " " + SmoldynVCellMapper.SmoldynKeyword.reflect);
// printWriter.println(SmoldynKeyword.action + " " + SmoldynKeyword.all + "(" + SmoldynKeyword.up + ") " + SmoldynKeyword.both + " " + SmoldynKeyword.reflect);
// get color after species
Color c = colors[sci + particleVariableList.size()];
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.color + " " + SmoldynVCellMapper.SmoldynKeyword.both + " " + c.getRed() / 255.0 + " " + c.getGreen() / 255.0 + " " + c.getBlue() / 255.0 + " 0.1");
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.polygon + " " + SmoldynVCellMapper.SmoldynKeyword.front + " " + SmoldynVCellMapper.SmoldynKeyword.edge);
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.polygon + " " + SmoldynVCellMapper.SmoldynKeyword.back + " " + SmoldynVCellMapper.SmoldynKeyword.edge);
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_panels + " " + SmoldynVCellMapper.SmoldynKeyword.tri + " " + triList.size());
for (TrianglePanel trianglePanel : triList) {
Triangle triangle = trianglePanel.triangle;
printWriter.print(SmoldynVCellMapper.SmoldynKeyword.panel + " " + SmoldynVCellMapper.SmoldynKeyword.tri);
switch(dimension) {
case 1:
printWriter.print(" " + triangle.getNodes(0).getX());
break;
case 2:
printWriter.print(" " + triangle.getNodes(0).getX() + " " + triangle.getNodes(0).getY());
printWriter.print(" " + triangle.getNodes(1).getX() + " " + triangle.getNodes(1).getY());
break;
case 3:
for (Node node : triangle.getNodes()) {
printWriter.print(" " + node.getX() + " " + node.getY() + " " + node.getZ());
}
break;
}
printWriter.println(" " + trianglePanel.name);
}
for (TrianglePanel triPanel : triList) {
neighborsForCurrentNode.clear();
for (Node node : triPanel.triangle.getNodes()) {
if (node == null) {
continue;
}
neighborsForCurrentNode.addAll(nodeTriMap.get(node));
}
neighborsForCurrentNode.remove(triPanel.name);
// printWriter.print(SmoldynKeyword.neighbors + " " +triPanel.name);
// to allow smoldyn read line length as 256, chop the neighbors to multiple lines
int maxNeighborCount = 4;
//
int count = 0;
for (String neigh : neighborsForCurrentNode) {
if (count % maxNeighborCount == 0) {
printWriter.println();
printWriter.print(SmoldynVCellMapper.SmoldynKeyword.neighbors + " " + triPanel.name);
}
printWriter.print(" " + neigh);
count++;
}
}
printWriter.println();
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.end_surface);
printWriter.println();
}
// write compartment
// printWriter.println("# bounding wall compartment");
// printWriter.println(SmoldynKeyword.start_compartment + " " + VCellSmoldynKeyword.bounding_wall_compartment);
// printWriter.println(SmoldynKeyword.surface + " " + VCellSmoldynKeyword.bounding_wall_surface_X);
// if (dimension > 1) {
// printWriter.println(SmoldynKeyword.surface + " " + VCellSmoldynKeyword.bounding_wall_surface_Y);
// if (dimension > 2) {
// printWriter.println(SmoldynKeyword.surface + " " + VCellSmoldynKeyword.bounding_wall_surface_Z);
// }
// }
// printWriter.println(SmoldynKeyword.end_compartment);
// printWriter.println();
}
}
use of cbit.vcell.geometry.surface.Node in project vcell by virtualcell.
the class SmoldynSurfaceTessellator method writeSurfaces.
protected void writeSurfaces() throws SolverException, ImageException, PropertyVetoException, GeometryException, ExpressionException {
GeometrySurfaceDescription geometrySurfaceDescription = resampledGeometry.getGeometrySurfaceDescription();
SurfaceClass[] surfaceClasses = geometrySurfaceDescription.getSurfaceClasses();
GeometrySpec geometrySpec = resampledGeometry.getGeometrySpec();
SubVolume[] surfaceGeometrySubVolumes = geometrySpec.getSubVolumes();
GeometricRegion[] AllGeometricRegions = resampledGeometry.getGeometrySurfaceDescription().getGeometricRegions();
ArrayList<SurfaceGeometricRegion> surfaceRegionList = new ArrayList<SurfaceGeometricRegion>();
ArrayList<VolumeGeometricRegion> volumeRegionList = new ArrayList<VolumeGeometricRegion>();
for (GeometricRegion geometricRegion : AllGeometricRegions) {
if (geometricRegion instanceof SurfaceGeometricRegion) {
surfaceRegionList.add((SurfaceGeometricRegion) geometricRegion);
} else if (geometricRegion instanceof VolumeGeometricRegion) {
volumeRegionList.add((VolumeGeometricRegion) geometricRegion);
} else {
throw new SolverException("unsupported geometric region type " + geometricRegion.getClass());
}
}
printWriter.println("# geometry");
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.dim + " " + dimension);
if (bHasNoSurface) {
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_compartment + " " + surfaceGeometrySubVolumes.length);
} else {
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_compartment + " " + (surfaceGeometrySubVolumes.length + 1));
// plus the surface which are bounding walls
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_surface + " " + (surfaceClasses.length + dimension));
}
printWriter.println();
// write boundaries and wall surfaces
writeWallSurfaces();
// for 3D ... smoldyn normal convension is triangle right-hand-rule normal points to the outside compartment subdomain.
if (!bHasNoSurface) {
membraneSubdomainTriangleMap = new HashMap<MembraneSubDomain, ArrayList<TrianglePanel>>();
// write surfaces
printWriter.println("# surfaces");
int triangleGlobalCount = 0;
int membraneIndex = -1;
SurfaceCollection surfaceCollection = geometrySurfaceDescription.getSurfaceCollection();
// pre-allocate collections used repeatedly in following loops; clear before reusing
HashMap<Node, Set<String>> nodeTriMap = new HashMap<>();
ArrayList<TrianglePanel> triList = new ArrayList<TrianglePanel>();
// use a sorted set to ensure neighbors written out is same order for reproducibility
SortedSet<String> neighborsForCurrentNode = new TreeSet<String>();
for (int sci = 0; sci < surfaceClasses.length; sci++) {
nodeTriMap.clear();
triList.clear();
int triLocalCount = 0;
SurfaceClass surfaceClass = surfaceClasses[sci];
GeometricRegion[] geometricRegions = geometrySurfaceDescription.getGeometricRegions(surfaceClass);
for (GeometricRegion gr : geometricRegions) {
SurfaceGeometricRegion sgr = (SurfaceGeometricRegion) gr;
VolumeGeometricRegion volRegion0 = (VolumeGeometricRegion) sgr.getAdjacentGeometricRegions()[0];
VolumeGeometricRegion volRegion1 = (VolumeGeometricRegion) sgr.getAdjacentGeometricRegions()[1];
SubVolume subVolume0 = volRegion0.getSubVolume();
SubVolume subVolume1 = volRegion1.getSubVolume();
CompartmentSubDomain compart0 = mathDesc.getCompartmentSubDomain(subVolume0.getName());
CompartmentSubDomain compart1 = mathDesc.getCompartmentSubDomain(subVolume1.getName());
MembraneSubDomain membraneSubDomain = mathDesc.getMembraneSubDomain(compart0, compart1);
if (membraneSubDomain == null) {
throw new SolverException(VCellErrorMessages.getSmoldynUnexpectedSurface(compart0, compart1));
}
int exteriorRegionID = volRegion0.getRegionID();
int interiorRegionID = volRegion1.getRegionID();
if (membraneSubDomain.getInsideCompartment() == compart0) {
exteriorRegionID = volRegion1.getRegionID();
interiorRegionID = volRegion0.getRegionID();
}
for (int j = 0; j < surfaceCollection.getSurfaceCount(); j++) {
Surface surface = surfaceCollection.getSurfaces(j);
if ((surface.getInteriorRegionIndex() == exteriorRegionID && surface.getExteriorRegionIndex() == interiorRegionID) || (surface.getInteriorRegionIndex() == interiorRegionID && surface.getExteriorRegionIndex() == exteriorRegionID)) {
// Polygon polygon = surface.getPolygons(k);
for (Polygon polygon : surface) {
if (polygonMembaneElementMap != null) {
membraneIndex = polygonMembaneElementMap.get(polygon).getMembraneIndex();
}
Node[] nodes = polygon.getNodes();
if (dimension == 2) {
// ignore z
Vect3d unitNormal = new Vect3d();
polygon.getUnitNormal(unitNormal);
unitNormal.set(unitNormal.getX(), unitNormal.getY(), 0);
int point0 = 0;
Vect3d v0 = new Vect3d(nodes[point0].getX(), nodes[point0].getY(), 0);
int point1 = 1;
Vect3d v1 = null;
for (point1 = 1; point1 < nodes.length; point1++) {
if (v0.getX() != nodes[point1].getX() || v0.getY() != nodes[point1].getY()) {
v1 = new Vect3d(nodes[point1].getX(), nodes[point1].getY(), 0);
break;
}
}
if (v1 == null) {
throw new RuntimeException("failed to generate surface");
}
Vect3d v01 = Vect3d.sub(v1, v0);
Vect3d unit01n = v01.cross(unitNormal);
unit01n.unit();
if (Math.abs(unit01n.getZ() - 1.0) < 1e-6) {
// v0 to v1 opposes vcell surface normal. it's already flipped.
Triangle triangle;
if (surface.getInteriorRegionIndex() == interiorRegionID) {
// we have to flipped it back
triangle = new Triangle(nodes[point1], nodes[point0], null);
} else {
triangle = new Triangle(nodes[point0], nodes[point1], null);
}
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle));
} else if (Math.abs(unit01n.getZ() + 1.0) < 1e-6) {
// v0 to v1 is in direction of vcell surface normal.
Triangle triangle;
if (surface.getInteriorRegionIndex() == interiorRegionID) {
triangle = new Triangle(nodes[point0], nodes[point1], null);
} else {
triangle = new Triangle(nodes[point1], nodes[point0], null);
}
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle));
} else {
throw new RuntimeException("failed to generate surface");
}
} else if (dimension == 3) {
Triangle triangle1;
Triangle triangle2;
if (surface.getInteriorRegionIndex() == interiorRegionID) {
// interior
triangle1 = new Triangle(nodes[0], nodes[1], nodes[2]);
triangle2 = new Triangle(nodes[0], nodes[2], nodes[3]);
} else {
triangle1 = new Triangle(nodes[2], nodes[1], nodes[0]);
triangle2 = new Triangle(nodes[3], nodes[2], nodes[0]);
}
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle1));
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle2));
}
}
}
}
}
// add triangles to node hash
for (TrianglePanel triPanel : triList) {
for (Node node : triPanel.triangle.getNodes()) {
if (node == null) {
continue;
}
Set<String> triNameSet = nodeTriMap.get(node);
if (triNameSet == null) {
triNameSet = new HashSet<String>();
nodeTriMap.put(node, triNameSet);
}
triNameSet.add(triPanel.name);
}
}
SubVolume[] adjacentSubvolums = surfaceClass.getAdjacentSubvolumes().toArray(new SubVolume[0]);
CompartmentSubDomain csd0 = simulation.getMathDescription().getCompartmentSubDomain(adjacentSubvolums[0].getName());
CompartmentSubDomain csd1 = simulation.getMathDescription().getCompartmentSubDomain(adjacentSubvolums[1].getName());
MembraneSubDomain membraneSubDomain = simulation.getMathDescription().getMembraneSubDomain(csd0, csd1);
membraneSubdomainTriangleMap.put(membraneSubDomain, triList);
final boolean initialMoleculesOnMembrane = (closestTriangles != null);
if (initialMoleculesOnMembrane) {
findClosestTriangles(membraneSubDomain, triList);
}
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.start_surface + " " + surfaceClass.getName());
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.action + " " + SmoldynVCellMapper.SmoldynKeyword.all + "(" + SmoldynVCellMapper.SmoldynKeyword.all + ") " + SmoldynVCellMapper.SmoldynKeyword.both + " " + SmoldynVCellMapper.SmoldynKeyword.reflect);
// printWriter.println(SmoldynKeyword.action + " " + SmoldynKeyword.all + "(" + SmoldynKeyword.up + ") " + SmoldynKeyword.both + " " + SmoldynKeyword.reflect);
Color c = colorForSurface(sci);
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.color + " " + SmoldynVCellMapper.SmoldynKeyword.both + " " + c.getRed() / 255.0 + " " + c.getGreen() / 255.0 + " " + c.getBlue() / 255.0 + " 0.1");
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.polygon + " " + SmoldynVCellMapper.SmoldynKeyword.front + " " + SmoldynVCellMapper.SmoldynKeyword.edge);
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.polygon + " " + SmoldynVCellMapper.SmoldynKeyword.back + " " + SmoldynVCellMapper.SmoldynKeyword.edge);
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_panels + " " + SmoldynVCellMapper.SmoldynKeyword.tri + " " + triList.size());
for (TrianglePanel trianglePanel : triList) {
Triangle triangle = trianglePanel.triangle;
printWriter.print(SmoldynVCellMapper.SmoldynKeyword.panel + " " + SmoldynVCellMapper.SmoldynKeyword.tri);
switch(dimension) {
case 1:
printWriter.print(" " + triangle.getNodes(0).getX());
break;
case 2:
printWriter.print(" " + triangle.getNodes(0).getX() + " " + triangle.getNodes(0).getY());
printWriter.print(" " + triangle.getNodes(1).getX() + " " + triangle.getNodes(1).getY());
break;
case 3:
for (Node node : triangle.getNodes()) {
printWriter.print(" " + node.getX() + " " + node.getY() + " " + node.getZ());
}
break;
}
printWriter.println(" " + trianglePanel.name);
}
for (TrianglePanel triPanel : triList) {
neighborsForCurrentNode.clear();
for (Node node : triPanel.triangle.getNodes()) {
if (node == null) {
continue;
}
neighborsForCurrentNode.addAll(nodeTriMap.get(node));
}
neighborsForCurrentNode.remove(triPanel.name);
// printWriter.print(SmoldynKeyword.neighbors + " " +triPanel.name);
// to allow smoldyn read line length as 256, chop the neighbors to multiple lines
int maxNeighborCount = 4;
//
int count = 0;
for (String neigh : neighborsForCurrentNode) {
if (count % maxNeighborCount == 0) {
printWriter.println();
printWriter.print(SmoldynVCellMapper.SmoldynKeyword.neighbors + " " + triPanel.name);
}
printWriter.print(" " + neigh);
count++;
}
}
printWriter.println();
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.end_surface);
printWriter.println();
}
}
}
use of cbit.vcell.geometry.surface.Node in project vcell by virtualcell.
the class RasterExporter method calculateCommonNeighbor.
private static CommonNeighb calculateCommonNeighbor(CartesianMesh mesh, RegionImage regionImage, MembraneElement membraneElementN0, MembraneElement membraneElementN1, int parentMembrIndex) {
// find common node
Quadrilateral quadp = (Quadrilateral) regionImage.getSurfacecollection().getSurfaces(regionImage.getQuadIndexToSurfAndFace().get(parentMembrIndex).getSurf()).getPolygons(regionImage.getQuadIndexToSurfAndFace().get(parentMembrIndex).getFace());
Quadrilateral quad0 = (Quadrilateral) regionImage.getSurfacecollection().getSurfaces(regionImage.getQuadIndexToSurfAndFace().get(membraneElementN0.getMembraneIndex()).getSurf()).getPolygons(regionImage.getQuadIndexToSurfAndFace().get(membraneElementN0.getMembraneIndex()).getFace());
Quadrilateral quad1 = (Quadrilateral) regionImage.getSurfacecollection().getSurfaces(regionImage.getQuadIndexToSurfAndFace().get(membraneElementN1.getMembraneIndex()).getSurf()).getPolygons(regionImage.getQuadIndexToSurfAndFace().get(membraneElementN1.getMembraneIndex()).getFace());
List<Node> nodesp = Arrays.asList(quadp.getNodes());
List<Node> nodes0 = Arrays.asList(quad0.getNodes());
List<Node> nodes1 = Arrays.asList(quad1.getNodes());
List<Node> intersectN = new ArrayList<>(nodes0);
intersectN.retainAll(nodes1);
intersectN.retainAll(nodesp);
if (intersectN.size() != 1) {
System.out.println("Couldn't find parent node");
return null;
}
ArrayList<Integer> commonNeighbors = new ArrayList<>();
findNeighborNeighborsWithNode(regionImage, membraneElementN0, intersectN.get(0), parentMembrIndex, commonNeighbors);
findNeighborNeighborsWithNode(regionImage, membraneElementN1, intersectN.get(0), parentMembrIndex, commonNeighbors);
return new CommonNeighb(intersectN.get(0), commonNeighbors);
}
use of cbit.vcell.geometry.surface.Node in project vcell by virtualcell.
the class GeometryFileWriter method write.
/**
* Insert the method's description here.
* Creation date: (7/19/2004 10:54:30 AM)
* @param geometrySurfaceDescription cbit.vcell.geometry.surface.GeometrySurfaceDescription
* @throws IOException
*/
public static void write(Writer writer, Geometry resampledGeometry) throws IOException {
//
// "name" name
// "dimension" dimension
// "extent" extentx extenty extentz
// "origin" originx originy originz
// "volumeRegions" num
// name totalVolume featureHandle
// "membraneRegions" num
// name totalArea volumeRegionIndex1 volumeRegionIndex2
// "volumeSamples" numX, numY, numZ
// uncompressed regionIndexs for each volume element
// compressed regionIndexs for each volume element
// "nodes" num
// nodeIndex x y z
// "cells" num
// cellIndex patchIndex node1 node2 node3 node4
// "celldata"
// insideVolumeIndex outsideVolumeIndex area normalx normaly normalz
//
//
// When we are writing volume regions, we sort regions so that ID is equal to index
//
writer.write("name " + resampledGeometry.getName() + "\n");
writer.write("dimension " + resampledGeometry.getDimension() + "\n");
org.vcell.util.Extent extent = resampledGeometry.getExtent();
org.vcell.util.Origin origin = resampledGeometry.getOrigin();
switch(resampledGeometry.getDimension()) {
case 1:
writer.write("size " + extent.getX() + "\n");
writer.write("origin " + origin.getX() + "\n");
break;
case 2:
writer.write("size " + extent.getX() + " " + extent.getY() + "\n");
writer.write("origin " + origin.getX() + " " + origin.getY() + "\n");
break;
case 3:
writer.write("size " + extent.getX() + " " + extent.getY() + " " + extent.getZ() + "\n");
writer.write("origin " + origin.getX() + " " + origin.getY() + " " + origin.getZ() + "\n");
break;
}
GeometrySurfaceDescription geoSurfaceDesc = resampledGeometry.getGeometrySurfaceDescription();
RegionImage regionImage = geoSurfaceDesc.getRegionImage();
SurfaceCollection surfaceCollection = geoSurfaceDesc.getSurfaceCollection();
GeometricRegion[] geometricRegions = geoSurfaceDesc.getGeometricRegions();
int numVolumeRegions = 0;
int numMembraneRegions = 0;
Vector<VolumeGeometricRegion> volRegionList = new Vector<VolumeGeometricRegion>();
if (geometricRegions != null) {
for (int i = 0; i < geometricRegions.length; i++) {
if (geometricRegions[i] instanceof VolumeGeometricRegion) {
numVolumeRegions++;
volRegionList.add((VolumeGeometricRegion) geometricRegions[i]);
} else if (geometricRegions[i] instanceof SurfaceGeometricRegion) {
numMembraneRegions++;
}
}
}
//
// get ordered array of volume regions (where "id" == index into array)... fail if impossible
//
java.util.Collections.sort(volRegionList, new Comparator<VolumeGeometricRegion>() {
public int compare(VolumeGeometricRegion reg1, VolumeGeometricRegion reg2) {
if (reg1.getRegionID() < reg2.getRegionID()) {
return -1;
} else if (reg1.getRegionID() > reg2.getRegionID()) {
return 1;
} else {
return 0;
}
}
public boolean equals(Object obj) {
return this == obj;
}
});
VolumeGeometricRegion[] volRegions = (VolumeGeometricRegion[]) org.vcell.util.BeanUtils.getArray(volRegionList, VolumeGeometricRegion.class);
writer.write("volumeRegions " + numVolumeRegions + "\n");
for (int i = 0; i < volRegions.length; i++) {
if (volRegions[i].getRegionID() != i) {
throw new RuntimeException("Region ID != Region Index, they must be the same!");
}
writer.write(volRegions[i].getName() + " " + volRegions[i].getSize() + " " + volRegions[i].getSubVolume().getHandle() + "\n");
}
writer.write("membraneRegions " + numMembraneRegions + "\n");
if (geometricRegions != null) {
for (int i = 0; i < geometricRegions.length; i++) {
if (geometricRegions[i] instanceof SurfaceGeometricRegion) {
SurfaceGeometricRegion surfaceRegion = (SurfaceGeometricRegion) geometricRegions[i];
GeometricRegion[] neighbors = surfaceRegion.getAdjacentGeometricRegions();
VolumeGeometricRegion insideRegion = (VolumeGeometricRegion) neighbors[0];
VolumeGeometricRegion outsideRegion = (VolumeGeometricRegion) neighbors[1];
writer.write(surfaceRegion.getName() + " " + surfaceRegion.getSize() + " " + insideRegion.getRegionID() + " " + outsideRegion.getRegionID() + "\n");
}
}
}
//
// write volume samples
//
ISize volumeSampleSize = geoSurfaceDesc.getVolumeSampleSize();
switch(resampledGeometry.getDimension()) {
case 1:
writer.write("volumeSamples " + volumeSampleSize.getX() + "\n");
break;
case 2:
writer.write("volumeSamples " + volumeSampleSize.getX() + " " + volumeSampleSize.getY() + "\n");
break;
case 3:
writer.write("volumeSamples " + volumeSampleSize.getX() + " " + volumeSampleSize.getY() + " " + volumeSampleSize.getZ() + "\n");
break;
}
// regionImage
if (regionImage != null) {
if (regionImage.getNumRegions() > 65536) {
throw new RuntimeException("cannot process a geometry with more than 65536 volume regions");
}
byte[] uncompressedRegionIDs = new byte[2 * regionImage.getNumX() * regionImage.getNumY() * regionImage.getNumZ()];
for (int i = 0, j = 0; i < uncompressedRegionIDs.length; i += 2, j++) {
int regindex = regionImage.getRegionInfoFromOffset(j).getRegionIndex();
uncompressedRegionIDs[i] = (byte) (regindex & 0x000000ff);
uncompressedRegionIDs[i + 1] = (byte) ((regindex & 0x0000ff00) >> 8);
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DeflaterOutputStream dos = new DeflaterOutputStream(bos);
dos.write(uncompressedRegionIDs, 0, uncompressedRegionIDs.length);
dos.close();
byte[] compressedRegionIDs = bos.toByteArray();
writer.write(org.vcell.util.Hex.toString(compressedRegionIDs) + "\n");
} else {
writer.write("\n");
}
//
if (surfaceCollection == null) {
throw new RuntimeException("geometry is not updated");
}
int numCells = surfaceCollection.getTotalPolygonCount();
writer.write("cells " + numCells + "\n");
// "celldata"
// insideVolumeIndex outsideVolumeIndex area normalx normaly normalz
//
int cellID = 0;
int dimension = resampledGeometry.getDimension();
double correctCoeff = 1;
if (dimension == 1) {
correctCoeff = extent.getY() * extent.getZ();
} else if (dimension == 2) {
correctCoeff = extent.getZ();
}
if (surfaceCollection != null) {
for (int i = 0; i < surfaceCollection.getSurfaceCount(); i++) {
Surface surface = surfaceCollection.getSurfaces(i);
int region1Outside = 0;
int region1Inside = 0;
for (int j = 0; j < surface.getPolygonCount(); j++) {
Quadrilateral polygon = (Quadrilateral) surface.getPolygons(j);
Node[] node = polygon.getNodes();
cbit.vcell.render.Vect3d elementCoord = new cbit.vcell.render.Vect3d();
int nodesOnBoundary = 0;
for (int k = 0; k < node.length; k++) {
if (!node[k].getMoveX() || (dimension > 1 && !node[k].getMoveY()) || (dimension == 3 && !node[k].getMoveZ())) {
nodesOnBoundary++;
}
}
if (nodesOnBoundary == 0) {
for (int k = 0; k < node.length; k++) {
elementCoord.add(new cbit.vcell.render.Vect3d(node[k].getX(), node[k].getY(), node[k].getZ()));
}
elementCoord.scale(0.25);
} else if (nodesOnBoundary == 2) {
for (int k = 0; k < node.length; k++) {
if (!node[k].getMoveX() || !node[k].getMoveY() || !node[k].getMoveZ()) {
elementCoord.add(new cbit.vcell.render.Vect3d(node[k].getX(), node[k].getY(), node[k].getZ()));
}
}
elementCoord.scale(0.5);
} else if (nodesOnBoundary == 3) {
for (int k = 0; k < node.length; k++) {
if (!node[k].getMoveX() && !node[k].getMoveY() || !node[k].getMoveY() && !node[k].getMoveZ() || !node[k].getMoveX() && !node[k].getMoveZ()) {
elementCoord.set(node[k].getX(), node[k].getY(), node[k].getZ());
}
}
} else {
throw new RuntimeException("Unexcepted number of nodes on boundary for a polygon: " + nodesOnBoundary);
}
cbit.vcell.render.Vect3d unitNormal = new cbit.vcell.render.Vect3d();
polygon.getUnitNormal(unitNormal);
int volNeighbor1Region = regionImage.getRegionInfoFromOffset(polygon.getVolIndexNeighbor1()).getRegionIndex();
int volNeighbor2Region = regionImage.getRegionInfoFromOffset(polygon.getVolIndexNeighbor2()).getRegionIndex();
if (surface.getExteriorRegionIndex() == volNeighbor1Region && surface.getInteriorRegionIndex() == volNeighbor2Region) {
region1Outside++;
}
if (surface.getExteriorRegionIndex() == volNeighbor2Region && surface.getInteriorRegionIndex() == volNeighbor1Region) {
region1Inside++;
}
writer.write(cellID + " " + polygon.getVolIndexNeighbor1() + " " + polygon.getVolIndexNeighbor2() + " " + polygon.getArea() / correctCoeff + " " + elementCoord.getX() + " " + elementCoord.getY() + " " + elementCoord.getZ() + " " + unitNormal.getX() + " " + unitNormal.getY() + " " + unitNormal.getZ() + "\n");
cellID++;
}
if (region1Inside != surface.getPolygonCount() && region1Outside != surface.getPolygonCount()) {
throw new RuntimeException("Volume neighbor regions not consistent: [total, inside, outside]=" + surface.getPolygonCount() + "," + region1Inside + "," + region1Outside + "]");
}
}
}
}
Aggregations