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 int tritmp = numtriangles * 3;
00123 f.append3(tritmp, tritmp+1, tritmp+2);
00124 numtriangles++;
00125
00126
00127 xx = tris[i].p[0].x;
00128 yy = tris[i].p[0].y;
00129 v.append3((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0],
00130 (float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1],
00131 (float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00132 xx = tris[i].p[1].x;
00133 yy = tris[i].p[1].y;
00134 v.append3((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0],
00135 (float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1],
00136 (float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00137 xx = tris[i].p[2].x;
00138 yy = tris[i].p[2].y;
00139 v.append3((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0],
00140 (float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1],
00141 (float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00142 }
00143 }
00144
00145 return tricount;
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 int IsoContour::Polygonise(const SQUARECELL grid, const float isolevel, LINE *triangles) {
00159 int i,ntriang;
00160 int cubeindex = grid.cubeindex;
00161 XY vertlist[12];
00162
00163
00164 if (edgeTable[cubeindex] & 1)
00165 VertexInterp(isolevel, grid, 0, 1, &vertlist[0]);
00166 if (edgeTable[cubeindex] & 2)
00167 VertexInterp(isolevel, grid, 1, 2, &vertlist[1]);
00168 if (edgeTable[cubeindex] & 4)
00169 VertexInterp(isolevel, grid, 2, 3, &vertlist[2]);
00170 if (edgeTable[cubeindex] & 8)
00171 VertexInterp(isolevel, grid, 3, 0, &vertlist[3]);
00172 if (edgeTable[cubeindex] & 16)
00173 VertexInterp(isolevel, grid, 4, 5, &vertlist[4]);
00174 if (edgeTable[cubeindex] & 32)
00175 VertexInterp(isolevel, grid, 5, 6, &vertlist[5]);
00176 if (edgeTable[cubeindex] & 64)
00177 VertexInterp(isolevel, grid, 6, 7, &vertlist[6]);
00178 if (edgeTable[cubeindex] & 128)
00179 VertexInterp(isolevel, grid, 7, 4, &vertlist[7]);
00180 if (edgeTable[cubeindex] & 256)
00181 VertexInterp(isolevel, grid, 0, 4, &vertlist[8]);
00182 if (edgeTable[cubeindex] & 512)
00183 VertexInterp(isolevel, grid, 1, 5, &vertlist[9]);
00184 if (edgeTable[cubeindex] & 1024)
00185 VertexInterp(isolevel, grid, 2, 6, &vertlist[10]);
00186 if (edgeTable[cubeindex] & 2048)
00187 VertexInterp(isolevel, grid, 3, 7, &vertlist[11]);
00188
00189
00190 ntriang = 0;
00191 for (i=0; lineTable[cubeindex][i]!=-1;i+=3) {
00192 triangles[ntriang].p[0] = vertlist[lineTable[cubeindex][i ]];
00193 triangles[ntriang].p[1] = vertlist[lineTable[cubeindex][i+1]];
00194 triangles[ntriang].p[2] = vertlist[lineTable[cubeindex][i+2]];
00195 ntriang++;
00196 }
00197
00198 return ntriang;
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208 void IsoContour::VertexInterp(float isolevel, const SQUARECELL grid, int ind1, int ind2, XY * vert) {
00209 float mu;
00210
00211 XY p1 = grid.p[ind1];
00212 XY p2 = grid.p[ind2];
00213 float valp1 = grid.val[ind1];
00214 float valp2 = grid.val[ind2];
00215
00216 if (fabs(isolevel-valp1) < 0.00001) {
00217 *vert = grid.p[ind1];
00218 return;
00219 }
00220
00221 if (fabs(isolevel-valp2) < 0.00001) {
00222 *vert = grid.p[ind2];
00223 return;
00224 }
00225
00226 if (fabs(valp1-valp2) < 0.00001) {
00227 *vert = grid.p[ind1];
00228 return;
00229 }
00230
00231 mu = (isolevel - valp1) / (valp2 - valp1);
00232
00233 vert->x = p1.x + mu * (p2.x - p1.x);
00234 vert->y = p1.y + mu * (p2.y - p1.y);
00235 }
00236