Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package azgracompress.data;
public final class Voxel {
/**
* Voxel dimensions.
*/
private final V3i dims;
public Voxel(final V3i voxelDims) {
dims = voxelDims;
}
/**
* Check whether the coordinates are inside voxel of dimension `dims`.
*
* @param x Zero based x coordinate.
* @param y Zero based y coordinate.
* @param z Zero based z coordinate.
* @return True if coordinates are inside this voxel.
*/
public boolean isInsideVoxel(final int x, final int y, final int z) {
return (((x >= 0) && (x < dims.getX())) && (y >= 0) && (y < dims.getY()) && (z >= 0) && (z < dims.getZ()));
}
/**
* Calculate the index inside data array for this voxel.
*
* @param x Zero based x coordinate.
* @param y Zero based y coordinate.
* @param z Zero based z coordinate.
* @return Index inside data array.
*/
public int dataIndex(final int x, final int y, final int z) {
return dataIndex(x, y, z, dims);
}
/**
* Calculate the index inside data array for voxel of given dimensions.
*
* @param x Zero based x coordinate.
* @param y Zero based y coordinate.
* @param z Zero based z coordinate.
* @param voxelDims Chunk dimensions.
* @return Index inside chunk dimension data array.
*/
public static int dataIndex(final int x, final int y, final int z, final V3i voxelDims) {
return (z * (voxelDims.getX() * voxelDims.getY())) + (y * voxelDims.getX()) + x;
}
/**
* Calculate required voxel count, which are needed when dividing dataset to voxels of given size.
*
* @param datasetDims Dataset dimensions.
* @param voxelDims One voxel dimensions.
* @return Number of voxels needed to divide the dataset.
*/
public static int calculateRequiredVoxelCount(final V3i datasetDims, final V3i voxelDims) {
final int xChunkCount = (int) Math.ceil((double) datasetDims.getX() / (double) voxelDims.getX());
final int yChunkCount = (int) Math.ceil((double) datasetDims.getY() / (double) voxelDims.getY());
final int zChunkCount = (int) Math.ceil((double) datasetDims.getZ() / (double) voxelDims.getZ());
return (xChunkCount * yChunkCount * zChunkCount);
}
public void reconstructFromVoxels(final V3i voxelDims,
final int[][] voxelData,
final short[][] reconstructedData,
final int planeIndexOffset) {
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
final int xVoxelCount = (int) Math.ceil((double) dims.getX() / (double) voxelDims.getX());
final int yVoxelCount = (int) Math.ceil((double) dims.getY() / (double) voxelDims.getY());
final int planeVoxelCount = xVoxelCount * yVoxelCount;
final int planeDimX = dims.getX();
final int planeDimY = dims.getY();
final int voxelDimX = voxelDims.getX();
final int voxelDimY = voxelDims.getY();
final int voxelDimZ = voxelDims.getZ();
int voxelOffset = 0;
for (int planeOffset = 0; planeOffset < dims.getZ(); planeOffset += voxelDimZ) {
for (int voxelZ = 0; voxelZ < voxelDimZ; voxelZ++) {
final int planeIndex = planeOffset + voxelZ;
if (planeIndex >= dims.getZ())
break;
for (int voxelIndex = 0; voxelIndex < planeVoxelCount; voxelIndex++) {
for (int voxelY = 0; voxelY < voxelDimY; voxelY++) {
final int dstY = ((voxelIndex / xVoxelCount) * voxelDimY) + voxelY;
if (dstY >= planeDimY) {
break;
}
for (int voxelX = 0; voxelX < voxelDimX; voxelX++) {
final int dstX = ((voxelIndex % xVoxelCount) * voxelDimX) + voxelX;
if (dstX >= planeDimX) {
break;
}
final int indexInsideVoxel = dataIndex(voxelX, voxelY, voxelZ, voxelDims);
final int indexInsidePlane = Block.index(dstX, dstY, planeDimX);
// reconstructedData are 2D data while voxelData are 3D data!
reconstructedData[planeIndexOffset + planeIndex][indexInsidePlane] =
(short) voxelData[(voxelOffset + voxelIndex)][indexInsideVoxel];
}
}
}
}
voxelOffset += planeVoxelCount;
}
}
/**
* Reconstruct an 3D dataset from voxels, which divided the original dataset.
*
* @param voxelDims Voxel dimensions.
* @param voxelData Voxel data.
* @return Dataset reconstructed from the voxel data.
*/
public ImageU16Dataset reconstructFromVoxelsToDataset(final V3i voxelDims, final int[][] voxelData) {
final short[][] reconstructedData = new short[dims.getZ()][dims.toV2i().multiplyTogether()];
reconstructFromVoxels(voxelDims, voxelData, reconstructedData, 0);
return new ImageU16Dataset(dims.toV2i(), dims.getZ(), reconstructedData);
}
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
public short[] reconstructFromVoxelsToVoxelArray(final V3i voxelDims, final int[][] voxelData) {
final short[] reconstructedVoxel = new short[(int) dims.multiplyTogether()];
final int xVoxelCount = (int) Math.ceil((double) dims.getX() / (double) voxelDims.getX());
final int yVoxelCount = (int) Math.ceil((double) dims.getY() / (double) voxelDims.getY());
final int planeVoxelCount = xVoxelCount * yVoxelCount;
final int planeDimX = dims.getX();
final int planeDimY = dims.getY();
final int voxelDimX = voxelDims.getX();
final int voxelDimY = voxelDims.getY();
final int voxelDimZ = voxelDims.getZ();
int voxelOffset = 0;
for (int planeOffset = 0; planeOffset < dims.getZ(); planeOffset += voxelDimZ) {
for (int voxelZ = 0; voxelZ < voxelDimZ; voxelZ++) {
final int planeIndex = planeOffset + voxelZ;
if (planeIndex >= dims.getZ())
break;
for (int voxelIndex = 0; voxelIndex < planeVoxelCount; voxelIndex++) {
for (int voxelY = 0; voxelY < voxelDimY; voxelY++) {
final int dstY = ((voxelIndex / xVoxelCount) * voxelDimY) + voxelY;
if (dstY >= planeDimY) {
break;
}
for (int voxelX = 0; voxelX < voxelDimX; voxelX++) {
final int dstX = ((voxelIndex % xVoxelCount) * voxelDimX) + voxelX;
if (dstX >= planeDimX) {
break;
}
final int indexInsideVoxel = dataIndex(voxelX, voxelY, voxelZ, voxelDims);
final int dstIndex = dataIndex(dstX, dstY, planeIndex);
if (dstIndex >= reconstructedVoxel.length) {
}
reconstructedVoxel[dstIndex] =
(short) voxelData[(voxelOffset + voxelIndex)][indexInsideVoxel];
}
}
}
}
voxelOffset += planeVoxelCount;
}
return reconstructedVoxel;
}
public final V3i getDims() {
return dims;
}