00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <string.h>
00012 #include <math.h>
00013 #include "Inform.h"
00014 #include "utilities.h"
00015
00016 #define ISOCONTOUR_INTERNAL 1
00017 #include "Isocontour.h"
00018 #include "VolumetricData.h"
00019
00020 IsoContour::IsoContour(void) {}
00021
00022 void IsoContour::clear(void) {
00023 numtriangles=0;
00024 v.clear();
00025 f.clear();
00026 }
00027
00028
00029 int IsoContour::compute(const VolumetricData *data, float isovalue, int step) {
00030 int x, y, z;
00031 int tricount=0;
00032
00033 vol=data;
00034
00035 xax[0] = (float) (vol->xaxis[0] / ((float) (vol->xsize - 1)));
00036 xax[1] = (float) (vol->xaxis[1] / ((float) (vol->xsize - 1)));
00037 xax[2] = (float) (vol->xaxis[2] / ((float) (vol->xsize - 1)));
00038
00039 yax[0] = (float) (vol->yaxis[0] / ((float) (vol->ysize - 1)));
00040 yax[1] = (float) (vol->yaxis[1] / ((float) (vol->ysize - 1)));
00041 yax[2] = (float) (vol->yaxis[2] / ((float) (vol->ysize - 1)));
00042
00043 zax[0] = (float) (vol->zaxis[0] / ((float) (vol->zsize - 1)));
00044 zax[1] = (float) (vol->zaxis[1] / ((float) (vol->zsize - 1)));
00045 zax[2] = (float) (vol->zaxis[2] / ((float) (vol->zsize - 1)));
00046
00047 for (z=0; z<(vol->zsize - step); z+=step) {
00048 for (y=0; y<(vol->ysize - step); y+=step) {
00049 for (x=0; x<(vol->xsize - step); x+=step) {
00050 tricount += DoCell(x, y, z, isovalue, step);
00051 }
00052 }
00053 }
00054
00055 return 1;
00056 }
00057
00058
00059
00060 int IsoContour::DoCell(int x, int y, int z, float isovalue, int step) {
00061 SQUARECELL gc;
00062 int addr, row, plane, rowstep, planestep, tricount;
00063 LINE tris[5];
00064
00065 row = vol->xsize;
00066 plane = vol->xsize * vol->ysize;
00067 addr = z*plane + y*row + x;
00068 rowstep = row*step;
00069 planestep = plane*step;
00070
00071 gc.val[0] = vol->data[addr ];
00072 gc.val[1] = vol->data[addr + step ];
00073 gc.val[3] = vol->data[addr + rowstep ];
00074 gc.val[2] = vol->data[addr + step + rowstep ];
00075 gc.val[4] = vol->data[addr + planestep];
00076 gc.val[5] = vol->data[addr + step + planestep];
00077 gc.val[7] = vol->data[addr + rowstep + planestep];
00078 gc.val[6] = vol->data[addr + step + rowstep + planestep];
00079
00080
00081
00082
00083
00084 int cubeindex = 0;
00085 if (gc.val[0] < isovalue) cubeindex |= 1;
00086 if (gc.val[1] < isovalue) cubeindex |= 2;
00087 if (gc.val[2] < isovalue) cubeindex |= 4;
00088 if (gc.val[3] < isovalue) cubeindex |= 8;
00089 if (gc.val[4] < isovalue) cubeindex |= 16;
00090 if (gc.val[5] < isovalue) cubeindex |= 32;
00091 if (gc.val[6] < isovalue) cubeindex |= 64;
00092 if (gc.val[7] < isovalue) cubeindex |= 128;
00093
00094
00095 if (edgeTable[cubeindex] == 0)
00096 return(0);
00097 gc.cubeindex = cubeindex;
00098
00099 gc.p[0].x = (float) x;
00100 gc.p[0].y = (float) y;
00101
00102 gc.p[1].x = (float) x + step;
00103 gc.p[1].y = (float) y;
00104
00105 gc.p[2].x = (float) x + step;
00106 gc.p[2].y = (float) y + step;
00107
00108 gc.p[3].x = (float) x;
00109 gc.p[3].y = (float) y + step;
00110
00111
00112
00113
00114 tricount = Polygonise(gc, isovalue, (LINE *) &tris);
00115
00116 if (tricount > 0) {
00117 int i;
00118
00119 for (i=0; i<tricount; i++) {
00120 float xx, yy, zz;
00121
00122 f.append(numtriangles * 3 );
00123 f.append(numtriangles * 3 + 1);
00124 f.append(numtriangles * 3 + 2);
00125 numtriangles++;
00126
00127
00128 xx = tris[i].p[0].x;
00129 yy = tris[i].p[0].y;
00130 v.append((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0]);
00131 v.append((float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1]);
00132 v.append((float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00133 xx = tris[i].p[1].x;
00134 yy = tris[i].p[1].y;
00135 v.append((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0]);
00136 v.append((float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1]);
00137 v.append((float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00138 xx = tris[i].p[2].x;
00139 yy = tris[i].p[2].y;
00140 v.append((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0]);
00141 v.append((float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1]);
00142 v.append((float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00143 }
00144 }
00145
00146 return tricount;
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 int IsoContour::Polygonise(const SQUARECELL grid, const float isolevel, LINE *triangles) {
00160 int i,ntriang;
00161 int cubeindex = grid.cubeindex;
00162 XY vertlist[12];
00163
00164
00165 if (edgeTable[cubeindex] & 1)
00166 VertexInterp(isolevel, grid, 0, 1, &vertlist[0]);
00167 if (edgeTable[cubeindex] & 2)
00168 VertexInterp(isolevel, grid, 1, 2, &vertlist[1]);
00169 if (edgeTable[cubeindex] & 4)
00170 VertexInterp(isolevel, grid, 2, 3, &vertlist[2]);
00171 if (edgeTable[cubeindex] & 8)
00172 VertexInterp(isolevel, grid, 3, 0, &vertlist[3]);
00173 if (edgeTable[cubeindex] & 16)
00174 VertexInterp(isolevel, grid, 4, 5, &vertlist[4]);
00175 if (edgeTable[cubeindex] & 32)
00176 VertexInterp(isolevel, grid, 5, 6, &vertlist[5]);
00177 if (edgeTable[cubeindex] & 64)
00178 VertexInterp(isolevel, grid, 6, 7, &vertlist[6]);
00179 if (edgeTable[cubeindex] & 128)
00180 VertexInterp(isolevel, grid, 7, 4, &vertlist[7]);
00181 if (edgeTable[cubeindex] & 256)
00182 VertexInterp(isolevel, grid, 0, 4, &vertlist[8]);
00183 if (edgeTable[cubeindex] & 512)
00184 VertexInterp(isolevel, grid, 1, 5, &vertlist[9]);
00185 if (edgeTable[cubeindex] & 1024)
00186 VertexInterp(isolevel, grid, 2, 6, &vertlist[10]);
00187 if (edgeTable[cubeindex] & 2048)
00188 VertexInterp(isolevel, grid, 3, 7, &vertlist[11]);
00189
00190
00191 ntriang = 0;
00192 for (i=0; lineTable[cubeindex][i]!=-1;i+=3) {
00193 triangles[ntriang].p[0] = vertlist[lineTable[cubeindex][i ]];
00194 triangles[ntriang].p[1] = vertlist[lineTable[cubeindex][i+1]];
00195 triangles[ntriang].p[2] = vertlist[lineTable[cubeindex][i+2]];
00196 ntriang++;
00197 }
00198
00199 return ntriang;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209 void IsoContour::VertexInterp(float isolevel, const SQUARECELL grid, int ind1, int ind2, XY * vert) {
00210 float mu;
00211
00212 XY p1 = grid.p[ind1];
00213 XY p2 = grid.p[ind2];
00214 float valp1 = grid.val[ind1];
00215 float valp2 = grid.val[ind2];
00216
00217 if (fabs(isolevel-valp1) < 0.00001) {
00218 *vert = grid.p[ind1];
00219 return;
00220 }
00221
00222 if (fabs(isolevel-valp2) < 0.00001) {
00223 *vert = grid.p[ind2];
00224 return;
00225 }
00226
00227 if (fabs(valp1-valp2) < 0.00001) {
00228 *vert = grid.p[ind1];
00229 return;
00230 }
00231
00232 mu = (isolevel - valp1) / (valp2 - valp1);
00233
00234 vert->x = p1.x + mu * (p2.x - p1.x);
00235 vert->y = p1.y + mu * (p2.y - p1.y);
00236 }
00237